Merge remote-tracking branch 'upstream/main' into vecmethods

This commit is contained in:
Geoffrey White
2020-08-20 13:29:28 +01:00
182 changed files with 14383 additions and 1218 deletions

View File

@@ -14,11 +14,12 @@ The following changes in version 1.26 affect C/C++ analysis in all applications.
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------|
| Inconsistent direction of for loop (`cpp/inconsistent-loop-direction`) | Fewer false positive results | The query now accounts for intentional wrapping of an unsigned loop counter. |
| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | | The precision of this query has been decreased from "high" to "medium". As a result, the query is still run but results are no longer displayed on LGTM by default. |
| Comparison result is always the same (`cpp/constant-comparison`) | More correct results | Bounds on expressions involving multiplication can now be determined in more cases. |
## Changes to libraries
* The models library now models some taint flows through `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
* The models library now models more taint flows through `std::string`.
* The models library now models many more taint flows through `std::string`.
* The `SimpleRangeAnalysis` library now supports multiplications of the form
`e1 * e2` when `e1` and `e2` are unsigned.
`e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant.

View File

@@ -0,0 +1,29 @@
# Improvements to C# analysis
The following changes in version 1.26 affect C# analysis in all applications.
## New queries
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|------------------------------|------------------------|-----------------------------------|
## Removal of old queries
## Changes to code extraction
* Partial method bodies are extracted. Previously, partial method bodies were skipped completely.
## Changes to libraries
## Changes to autobuilder
## Changes to tooling support
* The Abstract Syntax Tree of C# files can be printed in Visual Studio Code.

View File

@@ -14,6 +14,8 @@
- [pretty-format](https://www.npmjs.com/package/pretty-format)
- [stringify-object](https://www.npmjs.com/package/stringify-object)
* Analyzing files with the ".cjs" extension is now supported.
## New queries
| **Query** | **Tags** | **Purpose** |

View File

@@ -4,7 +4,7 @@
* user can result in integer overflow.
* @kind path-problem
* @problem.severity error
* @precision high
* @precision medium
* @id cpp/uncontrolled-allocation-size
* @tags reliability
* security

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext {
abstract predicate relevantFor(DataFlowCallable callable);
}
class CallContextAny extends CallContext, TAnyCallContext {
abstract class CallContextNoCall extends CallContext { }
class CallContextAny extends CallContextNoCall, TAnyCallContext {
override string toString() { result = "CcAny" }
override predicate relevantFor(DataFlowCallable callable) { any() }
}
abstract class CallContextCall extends CallContext { }
abstract class CallContextCall extends CallContext {
/** Holds if this call context may be `call`. */
bindingset[call]
abstract predicate matchesCall(DataFlowCall call);
}
class CallContextSpecificCall extends CallContextCall, TSpecificCall {
override string toString() {
@@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
recordDataFlowCallSite(getCall(), callable)
}
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
DataFlowCall getCall() { this = TSpecificCall(result) }
}
@@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | p.getEnclosingCallable() = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
}
class CallContextReturn extends CallContext, TReturn {
class CallContextReturn extends CallContextNoCall, TReturn {
override string toString() {
exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")")
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -539,6 +539,17 @@ class BinaryOperation extends Operation, @bin_op_expr {
/** Gets the right operand of this binary operation. */
Expr getRightOperand() { this.hasChild(result, 1) }
/**
* Holds if `e1` and `e2` (in either order) are the two operands of this
* binary operation.
*/
predicate hasOperands(Expr e1, Expr e2) {
exists(int i | i in [0, 1] |
this.hasChild(e1, i) and
this.hasChild(e2, 1 - i)
)
}
override string toString() { result = "... " + this.getOperator() + " ..." }
override predicate mayBeImpure() {

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext {
abstract predicate relevantFor(DataFlowCallable callable);
}
class CallContextAny extends CallContext, TAnyCallContext {
abstract class CallContextNoCall extends CallContext { }
class CallContextAny extends CallContextNoCall, TAnyCallContext {
override string toString() { result = "CcAny" }
override predicate relevantFor(DataFlowCallable callable) { any() }
}
abstract class CallContextCall extends CallContext { }
abstract class CallContextCall extends CallContext {
/** Holds if this call context may be `call`. */
bindingset[call]
abstract predicate matchesCall(DataFlowCall call);
}
class CallContextSpecificCall extends CallContextCall, TSpecificCall {
override string toString() {
@@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
recordDataFlowCallSite(getCall(), callable)
}
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
DataFlowCall getCall() { this = TSpecificCall(result) }
}
@@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | p.getEnclosingCallable() = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
}
class CallContextReturn extends CallContext, TReturn {
class CallContextReturn extends CallContextNoCall, TReturn {
override string toString() {
exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")")
}

View File

@@ -8,10 +8,13 @@ class StdBasicString extends TemplateClass {
}
/**
* The standard function `std::string.c_str`.
* The `std::string` functions `c_str` and `data`.
*/
class StdStringCStr extends TaintFunction {
StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") }
StdStringCStr() {
this.hasQualifiedName("std", "basic_string", "c_str") or
this.hasQualifiedName("std", "basic_string", "data")
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from string itself (qualifier) to return value
@@ -40,12 +43,16 @@ class StdStringPlus extends TaintFunction {
}
/**
* The `std::string` functions `operator+=` and `append`.
* The `std::string` functions `operator+=`, `append`, `insert` and
* `replace`. All of these functions combine the existing string
* with a new string (or character) from one of the arguments.
*/
class StdStringAppend extends TaintFunction {
StdStringAppend() {
this.hasQualifiedName("std", "basic_string", "operator+=") or
this.hasQualifiedName("std", "basic_string", "append")
this.hasQualifiedName("std", "basic_string", "append") or
this.hasQualifiedName("std", "basic_string", "insert") or
this.hasQualifiedName("std", "basic_string", "replace")
}
/**
@@ -58,6 +65,35 @@ class StdStringAppend extends TaintFunction {
getParameter(result).getType() = getDeclaringType().getTemplateArgument(0) // i.e. `std::basic_string::CharT`
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from string and parameter to string (qualifier) and return value
(
input.isQualifierObject() or
input.isParameterDeref(getAStringParameter())
) and
(
output.isQualifierObject() or
output.isReturnValueDeref()
)
}
}
/**
* The standard function `std::string.assign`.
*/
class StdStringAssign extends TaintFunction {
StdStringAssign() { this.hasQualifiedName("std", "basic_string", "assign") }
/**
* Gets the index of a parameter to this function that is a string (or
* character).
*/
int getAStringParameter() {
getParameter(result).getType() instanceof PointerType or
getParameter(result).getType() instanceof ReferenceType or
getParameter(result).getType() = getDeclaringType().getTemplateArgument(0) // i.e. `std::basic_string::CharT`
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to string itself (qualifier) and return value
input.isParameterDeref(getAStringParameter()) and
@@ -67,3 +103,45 @@ class StdStringAppend extends TaintFunction {
)
}
}
/**
* The standard function `std::string.copy`.
*/
class StdStringCopy extends TaintFunction {
StdStringCopy() { this.hasQualifiedName("std", "basic_string", "copy") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// copy(dest, num, pos)
input.isQualifierObject() and
output.isParameterDeref(0)
}
}
/**
* The standard function `std::string.substr`.
*/
class StdStringSubstr extends TaintFunction {
StdStringSubstr() { this.hasQualifiedName("std", "basic_string", "substr") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// substr(pos, num)
input.isQualifierObject() and
output.isReturnValue()
}
}
/**
* The standard function `std::string.swap`.
*/
class StdStringSwap extends TaintFunction {
StdStringSwap() { this.hasQualifiedName("std", "basic_string", "swap") }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// str1.swap(str2)
input.isQualifierObject() and
output.isParameterDeref(0)
or
input.isParameterDeref(0) and
output.isQualifierObject()
}
}

View File

@@ -127,7 +127,7 @@ private class UnsignedBitwiseAndExpr extends BitwiseAndExpr {
UnsignedBitwiseAndExpr() {
(
getLeftOperand().getFullyConverted().getType().getUnderlyingType().(IntegralType).isUnsigned() or
getLeftOperand().getFullyConverted().getValue().toInt() >= 0
getValue(getLeftOperand().getFullyConverted()).toInt() >= 0
) and
(
getRightOperand()
@@ -136,7 +136,7 @@ private class UnsignedBitwiseAndExpr extends BitwiseAndExpr {
.getUnderlyingType()
.(IntegralType)
.isUnsigned() or
getRightOperand().getFullyConverted().getValue().toInt() >= 0
getValue(getRightOperand().getFullyConverted()).toInt() >= 0
)
}
}
@@ -157,8 +157,90 @@ float safeFloor(float v) {
result = v
}
/** A `MulExpr` where exactly one operand is constant. */
private class MulByConstantExpr extends MulExpr {
float constant;
Expr operand;
MulByConstantExpr() {
exists(Expr constantExpr |
this.hasOperands(constantExpr, operand) and
constant = getValue(constantExpr.getFullyConverted()).toFloat() and
not exists(getValue(operand.getFullyConverted()).toFloat())
)
}
/** Gets the value of the constant operand. */
float getConstant() { result = constant }
/** Gets the non-constant operand. */
Expr getOperand() { result = operand }
}
private class UnsignedMulExpr extends MulExpr {
UnsignedMulExpr() { this.getType().(IntegralType).isUnsigned() }
UnsignedMulExpr() {
this.getType().(IntegralType).isUnsigned() and
// Avoid overlap. It should be slightly cheaper to analyze
// `MulByConstantExpr`.
not this instanceof MulByConstantExpr
}
}
/**
* Holds if `expr` is effectively a multiplication of `operand` with the
* positive constant `positive`.
*/
private predicate effectivelyMultipliesByPositive(Expr expr, Expr operand, float positive) {
operand = expr.(MulByConstantExpr).getOperand() and
positive = expr.(MulByConstantExpr).getConstant() and
positive >= 0.0 // includes positive zero
or
operand = expr.(UnaryPlusExpr).getOperand() and
positive = 1.0
or
operand = expr.(CommaExpr).getRightOperand() and
positive = 1.0
or
operand = expr.(StmtExpr).getResultExpr() and
positive = 1.0
}
/**
* Holds if `expr` is effectively a multiplication of `operand` with the
* negative constant `negative`.
*/
private predicate effectivelyMultipliesByNegative(Expr expr, Expr operand, float negative) {
operand = expr.(MulByConstantExpr).getOperand() and
negative = expr.(MulByConstantExpr).getConstant() and
negative < 0.0 // includes negative zero
or
operand = expr.(UnaryMinusExpr).getOperand() and
negative = -1.0
}
private class AssignMulByConstantExpr extends AssignMulExpr {
float constant;
AssignMulByConstantExpr() { constant = getValue(this.getRValue().getFullyConverted()).toFloat() }
float getConstant() { result = constant }
}
private class AssignMulByPositiveConstantExpr extends AssignMulByConstantExpr {
AssignMulByPositiveConstantExpr() { constant >= 0.0 }
}
private class AssignMulByNegativeConstantExpr extends AssignMulByConstantExpr {
AssignMulByNegativeConstantExpr() { constant < 0.0 }
}
private class UnsignedAssignMulExpr extends AssignMulExpr {
UnsignedAssignMulExpr() {
this.getType().(IntegralType).isUnsigned() and
// Avoid overlap. It should be slightly cheaper to analyze
// `AssignMulByConstantExpr`.
not this instanceof AssignMulByConstantExpr
}
}
/** Set of expressions which we know how to analyze. */
@@ -169,9 +251,9 @@ private predicate analyzableExpr(Expr e) {
(
exists(getValue(e).toFloat())
or
e instanceof UnaryPlusExpr
effectivelyMultipliesByPositive(e, _, _)
or
e instanceof UnaryMinusExpr
effectivelyMultipliesByNegative(e, _, _)
or
e instanceof MinExpr
or
@@ -191,14 +273,14 @@ private predicate analyzableExpr(Expr e) {
or
e instanceof AssignSubExpr
or
e instanceof UnsignedAssignMulExpr
or
e instanceof AssignMulByConstantExpr
or
e instanceof CrementOperation
or
e instanceof RemExpr
or
e instanceof CommaExpr
or
e instanceof StmtExpr
or
// A conversion is analyzable, provided that its child has an arithmetic
// type. (Sometimes the child is a reference type, and so does not get
// any bounds.) Rather than checking whether the type of the child is
@@ -213,7 +295,7 @@ private predicate analyzableExpr(Expr e) {
e instanceof UnsignedBitwiseAndExpr
or
// `>>` by a constant
exists(e.(RShiftExpr).getRightOperand().getValue())
exists(getValue(e.(RShiftExpr).getRightOperand()))
or
// A modeled expression for range analysis
e instanceof SimpleRangeAnalysisExpr
@@ -237,25 +319,33 @@ private predicate defDependsOnDef(
// Definitions with a defining value.
exists(Expr expr | assignmentDef(def, v, expr) | exprDependsOnDef(expr, srcDef, srcVar))
or
exists(AssignAddExpr assignAdd, RangeSsaDefinition nextDef |
exists(AssignAddExpr assignAdd |
def = assignAdd and
assignAdd.getLValue() = nextDef.getAUse(v)
|
defDependsOnDef(nextDef, v, srcDef, srcVar) or
exprDependsOnDef(assignAdd.getRValue(), srcDef, srcVar)
def.getAVariable() = v and
exprDependsOnDef(assignAdd.getAnOperand(), srcDef, srcVar)
)
or
exists(AssignSubExpr assignSub, RangeSsaDefinition nextDef |
exists(AssignSubExpr assignSub |
def = assignSub and
assignSub.getLValue() = nextDef.getAUse(v)
|
defDependsOnDef(nextDef, v, srcDef, srcVar) or
exprDependsOnDef(assignSub.getRValue(), srcDef, srcVar)
def.getAVariable() = v and
exprDependsOnDef(assignSub.getAnOperand(), srcDef, srcVar)
)
or
exists(UnsignedAssignMulExpr assignMul |
def = assignMul and
def.getAVariable() = v and
exprDependsOnDef(assignMul.getAnOperand(), srcDef, srcVar)
)
or
exists(AssignMulByConstantExpr assignMul |
def = assignMul and
def.getAVariable() = v and
exprDependsOnDef(assignMul.getLValue(), srcDef, srcVar)
)
or
exists(CrementOperation crem |
def = crem and
crem.getOperand() = v.getAnAccess() and
def.getAVariable() = v and
exprDependsOnDef(crem.getOperand(), srcDef, srcVar)
)
or
@@ -268,12 +358,14 @@ private predicate defDependsOnDef(
* the structure of `getLowerBoundsImpl` and `getUpperBoundsImpl`.
*/
private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVariable srcVar) {
exists(UnaryMinusExpr negateExpr | e = negateExpr |
exprDependsOnDef(negateExpr.getOperand(), srcDef, srcVar)
exists(Expr operand |
effectivelyMultipliesByNegative(e, operand, _) and
exprDependsOnDef(operand, srcDef, srcVar)
)
or
exists(UnaryPlusExpr plusExpr | e = plusExpr |
exprDependsOnDef(plusExpr.getOperand(), srcDef, srcVar)
exists(Expr operand |
effectivelyMultipliesByPositive(e, operand, _) and
exprDependsOnDef(operand, srcDef, srcVar)
)
or
exists(MinExpr minExpr | e = minExpr | exprDependsOnDef(minExpr.getAnOperand(), srcDef, srcVar))
@@ -302,20 +394,20 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar)
)
or
exists(UnsignedAssignMulExpr mulExpr | e = mulExpr |
exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar)
)
or
exists(AssignMulByConstantExpr mulExpr | e = mulExpr |
exprDependsOnDef(mulExpr.getLValue(), srcDef, srcVar)
)
or
exists(CrementOperation crementExpr | e = crementExpr |
exprDependsOnDef(crementExpr.getOperand(), srcDef, srcVar)
)
or
exists(RemExpr remExpr | e = remExpr | exprDependsOnDef(remExpr.getAnOperand(), srcDef, srcVar))
or
exists(CommaExpr commaExpr | e = commaExpr |
exprDependsOnDef(commaExpr.getRightOperand(), srcDef, srcVar)
)
or
exists(StmtExpr stmtExpr | e = stmtExpr |
exprDependsOnDef(stmtExpr.getResultExpr(), srcDef, srcVar)
)
or
exists(Conversion convExpr | e = convExpr | exprDependsOnDef(convExpr.getExpr(), srcDef, srcVar))
or
// unsigned `&`
@@ -327,7 +419,7 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
// `>>` by a constant
exists(RShiftExpr rs |
rs = e and
exists(rs.getRightOperand().getValue()) and
exists(getValue(rs.getRightOperand())) and
exprDependsOnDef(rs.getLeftOperand(), srcDef, srcVar)
)
or
@@ -580,15 +672,16 @@ deprecated predicate positive_overflow(Expr expr) { exprMightOverflowPositively(
/** Only to be called by `getTruncatedLowerBounds`. */
private float getLowerBoundsImpl(Expr expr) {
exists(UnaryPlusExpr plusExpr |
expr = plusExpr and
result = getFullyConvertedLowerBounds(plusExpr.getOperand())
exists(Expr operand, float operandLow, float positive |
effectivelyMultipliesByPositive(expr, operand, positive) and
operandLow = getFullyConvertedLowerBounds(operand) and
result = positive * operandLow
)
or
exists(UnaryMinusExpr negateExpr, float xHigh |
expr = negateExpr and
xHigh = getFullyConvertedUpperBounds(negateExpr.getOperand()) and
result = -xHigh
exists(Expr operand, float operandHigh, float negative |
effectivelyMultipliesByNegative(expr, operand, negative) and
operandHigh = getFullyConvertedUpperBounds(operand) and
result = negative * operandHigh
)
or
exists(MinExpr minExpr |
@@ -669,6 +762,25 @@ private float getLowerBoundsImpl(Expr expr) {
result = addRoundingDown(xLow, -yHigh)
)
or
exists(UnsignedAssignMulExpr mulExpr, float xLow, float yLow |
expr = mulExpr and
xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and
yLow = getFullyConvertedLowerBounds(mulExpr.getRValue()) and
result = xLow * yLow
)
or
exists(AssignMulByPositiveConstantExpr mulExpr, float xLow |
expr = mulExpr and
xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and
result = xLow * mulExpr.getConstant()
)
or
exists(AssignMulByNegativeConstantExpr mulExpr, float xHigh |
expr = mulExpr and
xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and
result = xHigh * mulExpr.getConstant()
)
or
exists(PrefixIncrExpr incrExpr, float xLow |
expr = incrExpr and
xLow = getFullyConvertedLowerBounds(incrExpr.getOperand()) and
@@ -713,16 +825,6 @@ private float getLowerBoundsImpl(Expr expr) {
)
)
or
exists(CommaExpr commaExpr |
expr = commaExpr and
result = getFullyConvertedLowerBounds(commaExpr.getRightOperand())
)
or
exists(StmtExpr stmtExpr |
expr = stmtExpr and
result = getFullyConvertedLowerBounds(stmtExpr.getResultExpr())
)
or
// If the conversion is to an arithmetic type then we just return the
// lower bound of the child. We do not need to handle truncation and
// overflow here, because that is done in `getTruncatedLowerBounds`.
@@ -751,7 +853,7 @@ private float getLowerBoundsImpl(Expr expr) {
exists(RShiftExpr rsExpr, float left, int right |
rsExpr = expr and
left = getFullyConvertedLowerBounds(rsExpr.getLeftOperand()) and
right = rsExpr.getRightOperand().getFullyConverted().getValue().toInt() and
right = getValue(rsExpr.getRightOperand().getFullyConverted()).toInt() and
result = safeFloor(left / 2.pow(right))
)
or
@@ -764,15 +866,16 @@ private float getLowerBoundsImpl(Expr expr) {
/** Only to be called by `getTruncatedUpperBounds`. */
private float getUpperBoundsImpl(Expr expr) {
exists(UnaryPlusExpr plusExpr |
expr = plusExpr and
result = getFullyConvertedUpperBounds(plusExpr.getOperand())
exists(Expr operand, float operandHigh, float positive |
effectivelyMultipliesByPositive(expr, operand, positive) and
operandHigh = getFullyConvertedUpperBounds(operand) and
result = positive * operandHigh
)
or
exists(UnaryMinusExpr negateExpr, float xLow |
expr = negateExpr and
xLow = getFullyConvertedLowerBounds(negateExpr.getOperand()) and
result = -xLow
exists(Expr operand, float operandLow, float negative |
effectivelyMultipliesByNegative(expr, operand, negative) and
operandLow = getFullyConvertedLowerBounds(operand) and
result = negative * operandLow
)
or
exists(MaxExpr maxExpr |
@@ -853,6 +956,25 @@ private float getUpperBoundsImpl(Expr expr) {
result = addRoundingUp(xHigh, -yLow)
)
or
exists(UnsignedAssignMulExpr mulExpr, float xHigh, float yHigh |
expr = mulExpr and
xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and
yHigh = getFullyConvertedUpperBounds(mulExpr.getRValue()) and
result = xHigh * yHigh
)
or
exists(AssignMulByPositiveConstantExpr mulExpr, float xHigh |
expr = mulExpr and
xHigh = getFullyConvertedUpperBounds(mulExpr.getLValue()) and
result = xHigh * mulExpr.getConstant()
)
or
exists(AssignMulByNegativeConstantExpr mulExpr, float xLow |
expr = mulExpr and
xLow = getFullyConvertedLowerBounds(mulExpr.getLValue()) and
result = xLow * mulExpr.getConstant()
)
or
exists(PrefixIncrExpr incrExpr, float xHigh |
expr = incrExpr and
xHigh = getFullyConvertedUpperBounds(incrExpr.getOperand()) and
@@ -895,16 +1017,6 @@ private float getUpperBoundsImpl(Expr expr) {
)
)
or
exists(CommaExpr commaExpr |
expr = commaExpr and
result = getFullyConvertedUpperBounds(commaExpr.getRightOperand())
)
or
exists(StmtExpr stmtExpr |
expr = stmtExpr and
result = getFullyConvertedUpperBounds(stmtExpr.getResultExpr())
)
or
// If the conversion is to an arithmetic type then we just return the
// upper bound of the child. We do not need to handle truncation and
// overflow here, because that is done in `getTruncatedUpperBounds`.
@@ -935,7 +1047,7 @@ private float getUpperBoundsImpl(Expr expr) {
exists(RShiftExpr rsExpr, float left, int right |
rsExpr = expr and
left = getFullyConvertedUpperBounds(rsExpr.getLeftOperand()) and
right = rsExpr.getRightOperand().getFullyConverted().getValue().toInt() and
right = getValue(rsExpr.getRightOperand().getFullyConverted()).toInt() and
result = safeFloor(left / 2.pow(right))
)
or
@@ -1089,6 +1201,28 @@ private float getDefLowerBoundsImpl(RangeSsaDefinition def, StackVariable v) {
result = addRoundingDown(lhsLB, -rhsUB)
)
or
exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef, float lhsLB, float rhsLB |
def = assignMul and
assignMul.getLValue() = nextDef.getAUse(v) and
lhsLB = getDefLowerBounds(nextDef, v) and
rhsLB = getFullyConvertedLowerBounds(assignMul.getRValue()) and
result = lhsLB * rhsLB
)
or
exists(AssignMulByPositiveConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsLB |
def = assignMul and
assignMul.getLValue() = nextDef.getAUse(v) and
lhsLB = getDefLowerBounds(nextDef, v) and
result = lhsLB * assignMul.getConstant()
)
or
exists(AssignMulByNegativeConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsUB |
def = assignMul and
assignMul.getLValue() = nextDef.getAUse(v) and
lhsUB = getDefUpperBounds(nextDef, v) and
result = lhsUB * assignMul.getConstant()
)
or
exists(IncrementOperation incr, float newLB |
def = incr and
incr.getOperand() = v.getAnAccess() and
@@ -1131,6 +1265,28 @@ private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) {
result = addRoundingUp(lhsUB, -rhsLB)
)
or
exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef, float lhsUB, float rhsUB |
def = assignMul and
assignMul.getLValue() = nextDef.getAUse(v) and
lhsUB = getDefUpperBounds(nextDef, v) and
rhsUB = getFullyConvertedUpperBounds(assignMul.getRValue()) and
result = lhsUB * rhsUB
)
or
exists(AssignMulByPositiveConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsUB |
def = assignMul and
assignMul.getLValue() = nextDef.getAUse(v) and
lhsUB = getDefUpperBounds(nextDef, v) and
result = lhsUB * assignMul.getConstant()
)
or
exists(AssignMulByNegativeConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsLB |
def = assignMul and
assignMul.getLValue() = nextDef.getAUse(v) and
lhsLB = getDefLowerBounds(nextDef, v) and
result = lhsLB * assignMul.getConstant()
)
or
exists(IncrementOperation incr, float newUB |
def = incr and
incr.getOperand() = v.getAnAccess() and

View File

@@ -457,6 +457,7 @@
| string.cpp:160:8:160:9 | s3 | string.cpp:161:3:161:4 | s6 | |
| string.cpp:160:8:160:9 | s3 | string.cpp:162:8:162:9 | s6 | |
| string.cpp:161:3:161:4 | ref arg s6 | string.cpp:162:8:162:9 | s6 | |
| string.cpp:161:3:161:4 | s6 | string.cpp:161:6:161:6 | call to operator+= | TAINT |
| string.cpp:161:9:161:10 | s4 | string.cpp:161:3:161:4 | ref arg s6 | TAINT |
| string.cpp:161:9:161:10 | s4 | string.cpp:161:6:161:6 | call to operator+= | TAINT |
| string.cpp:164:8:164:9 | s3 | string.cpp:164:3:164:9 | ... = ... | |
@@ -465,15 +466,18 @@
| string.cpp:164:8:164:9 | s3 | string.cpp:167:8:167:9 | s7 | |
| string.cpp:165:3:165:4 | ref arg s7 | string.cpp:166:3:166:4 | s7 | |
| string.cpp:165:3:165:4 | ref arg s7 | string.cpp:167:8:167:9 | s7 | |
| string.cpp:165:3:165:4 | s7 | string.cpp:165:6:165:6 | call to operator+= | TAINT |
| string.cpp:165:9:165:14 | call to source | string.cpp:165:3:165:4 | ref arg s7 | TAINT |
| string.cpp:165:9:165:14 | call to source | string.cpp:165:6:165:6 | call to operator+= | TAINT |
| string.cpp:166:3:166:4 | ref arg s7 | string.cpp:167:8:167:9 | s7 | |
| string.cpp:166:3:166:4 | s7 | string.cpp:166:6:166:6 | call to operator+= | TAINT |
| string.cpp:166:9:166:11 | | string.cpp:166:3:166:4 | ref arg s7 | TAINT |
| string.cpp:166:9:166:11 | | string.cpp:166:6:166:6 | call to operator+= | TAINT |
| string.cpp:169:8:169:9 | s3 | string.cpp:169:3:169:9 | ... = ... | |
| string.cpp:169:8:169:9 | s3 | string.cpp:170:3:170:4 | s8 | |
| string.cpp:169:8:169:9 | s3 | string.cpp:171:8:171:9 | s8 | |
| string.cpp:170:3:170:4 | ref arg s8 | string.cpp:171:8:171:9 | s8 | |
| string.cpp:170:3:170:4 | s8 | string.cpp:170:6:170:11 | call to append | TAINT |
| string.cpp:170:13:170:14 | s4 | string.cpp:170:3:170:4 | ref arg s8 | TAINT |
| string.cpp:170:13:170:14 | s4 | string.cpp:170:6:170:11 | call to append | TAINT |
| string.cpp:173:8:173:9 | s3 | string.cpp:173:3:173:9 | ... = ... | |
@@ -482,9 +486,11 @@
| string.cpp:173:8:173:9 | s3 | string.cpp:176:8:176:9 | s9 | |
| string.cpp:174:3:174:4 | ref arg s9 | string.cpp:175:3:175:4 | s9 | |
| string.cpp:174:3:174:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | |
| string.cpp:174:3:174:4 | s9 | string.cpp:174:6:174:11 | call to append | TAINT |
| string.cpp:174:13:174:18 | call to source | string.cpp:174:3:174:4 | ref arg s9 | TAINT |
| string.cpp:174:13:174:18 | call to source | string.cpp:174:6:174:11 | call to append | TAINT |
| string.cpp:175:3:175:4 | ref arg s9 | string.cpp:176:8:176:9 | s9 | |
| string.cpp:175:3:175:4 | s9 | string.cpp:175:6:175:11 | call to append | TAINT |
| string.cpp:175:13:175:15 | | string.cpp:175:3:175:4 | ref arg s9 | TAINT |
| string.cpp:175:13:175:15 | | string.cpp:175:6:175:11 | call to append | TAINT |
| string.cpp:180:19:180:23 | abc | string.cpp:180:19:180:24 | call to basic_string | TAINT |
@@ -492,8 +498,185 @@
| string.cpp:180:19:180:24 | call to basic_string | string.cpp:184:8:184:10 | s10 | |
| string.cpp:181:12:181:26 | call to source | string.cpp:183:17:183:17 | c | |
| string.cpp:183:3:183:5 | ref arg s10 | string.cpp:184:8:184:10 | s10 | |
| string.cpp:183:3:183:5 | s10 | string.cpp:183:7:183:12 | call to append | TAINT |
| string.cpp:183:17:183:17 | c | string.cpp:183:3:183:5 | ref arg s10 | TAINT |
| string.cpp:183:17:183:17 | c | string.cpp:183:7:183:12 | call to append | TAINT |
| string.cpp:189:17:189:23 | hello | string.cpp:189:17:189:24 | call to basic_string | TAINT |
| string.cpp:189:17:189:24 | call to basic_string | string.cpp:195:17:195:18 | s1 | |
| string.cpp:189:17:189:24 | call to basic_string | string.cpp:204:17:204:18 | s1 | |
| string.cpp:190:17:190:22 | call to source | string.cpp:190:17:190:25 | call to basic_string | TAINT |
| string.cpp:190:17:190:25 | call to basic_string | string.cpp:198:17:198:18 | s2 | |
| string.cpp:191:11:191:25 | call to source | string.cpp:201:21:201:21 | c | |
| string.cpp:192:14:192:15 | call to basic_string | string.cpp:195:7:195:8 | s3 | |
| string.cpp:192:14:192:15 | call to basic_string | string.cpp:196:7:196:8 | s3 | |
| string.cpp:192:18:192:19 | call to basic_string | string.cpp:198:7:198:8 | s4 | |
| string.cpp:192:18:192:19 | call to basic_string | string.cpp:199:7:199:8 | s4 | |
| string.cpp:192:22:192:23 | call to basic_string | string.cpp:201:7:201:8 | s5 | |
| string.cpp:192:22:192:23 | call to basic_string | string.cpp:202:7:202:8 | s5 | |
| string.cpp:193:17:193:22 | call to source | string.cpp:193:17:193:25 | call to basic_string | TAINT |
| string.cpp:193:17:193:25 | call to basic_string | string.cpp:204:7:204:8 | s6 | |
| string.cpp:193:17:193:25 | call to basic_string | string.cpp:205:7:205:8 | s6 | |
| string.cpp:195:7:195:8 | ref arg s3 | string.cpp:196:7:196:8 | s3 | |
| string.cpp:195:17:195:18 | s1 | string.cpp:195:7:195:8 | ref arg s3 | TAINT |
| string.cpp:195:17:195:18 | s1 | string.cpp:195:10:195:15 | call to assign | TAINT |
| string.cpp:198:7:198:8 | ref arg s4 | string.cpp:199:7:199:8 | s4 | |
| string.cpp:198:17:198:18 | s2 | string.cpp:198:7:198:8 | ref arg s4 | TAINT |
| string.cpp:198:17:198:18 | s2 | string.cpp:198:10:198:15 | call to assign | TAINT |
| string.cpp:201:7:201:8 | ref arg s5 | string.cpp:202:7:202:8 | s5 | |
| string.cpp:201:21:201:21 | c | string.cpp:201:7:201:8 | ref arg s5 | TAINT |
| string.cpp:201:21:201:21 | c | string.cpp:201:10:201:15 | call to assign | TAINT |
| string.cpp:204:7:204:8 | ref arg s6 | string.cpp:205:7:205:8 | s6 | |
| string.cpp:204:17:204:18 | s1 | string.cpp:204:7:204:8 | ref arg s6 | TAINT |
| string.cpp:204:17:204:18 | s1 | string.cpp:204:10:204:15 | call to assign | TAINT |
| string.cpp:209:17:209:23 | hello | string.cpp:209:17:209:24 | call to basic_string | TAINT |
| string.cpp:209:17:209:24 | call to basic_string | string.cpp:214:7:214:8 | s1 | |
| string.cpp:209:17:209:24 | call to basic_string | string.cpp:215:20:215:21 | s1 | |
| string.cpp:209:17:209:24 | call to basic_string | string.cpp:219:20:219:21 | s1 | |
| string.cpp:209:17:209:24 | call to basic_string | string.cpp:222:7:222:8 | s1 | |
| string.cpp:209:17:209:24 | call to basic_string | string.cpp:226:7:226:8 | s1 | |
| string.cpp:210:17:210:22 | call to source | string.cpp:210:17:210:25 | call to basic_string | TAINT |
| string.cpp:210:17:210:25 | call to basic_string | string.cpp:218:7:218:8 | s2 | |
| string.cpp:210:17:210:25 | call to basic_string | string.cpp:223:20:223:21 | s2 | |
| string.cpp:211:11:211:25 | call to source | string.cpp:227:24:227:24 | c | |
| string.cpp:214:7:214:8 | s1 | string.cpp:214:2:214:8 | ... = ... | |
| string.cpp:214:7:214:8 | s1 | string.cpp:215:7:215:8 | s3 | |
| string.cpp:214:7:214:8 | s1 | string.cpp:216:7:216:8 | s3 | |
| string.cpp:215:7:215:8 | ref arg s3 | string.cpp:216:7:216:8 | s3 | |
| string.cpp:215:7:215:8 | s3 | string.cpp:215:10:215:15 | call to insert | TAINT |
| string.cpp:215:20:215:21 | s1 | string.cpp:215:7:215:8 | ref arg s3 | TAINT |
| string.cpp:215:20:215:21 | s1 | string.cpp:215:10:215:15 | call to insert | TAINT |
| string.cpp:218:7:218:8 | s2 | string.cpp:218:2:218:8 | ... = ... | |
| string.cpp:218:7:218:8 | s2 | string.cpp:219:7:219:8 | s4 | |
| string.cpp:218:7:218:8 | s2 | string.cpp:220:7:220:8 | s4 | |
| string.cpp:219:7:219:8 | ref arg s4 | string.cpp:220:7:220:8 | s4 | |
| string.cpp:219:7:219:8 | s4 | string.cpp:219:10:219:15 | call to insert | TAINT |
| string.cpp:219:20:219:21 | s1 | string.cpp:219:7:219:8 | ref arg s4 | TAINT |
| string.cpp:219:20:219:21 | s1 | string.cpp:219:10:219:15 | call to insert | TAINT |
| string.cpp:222:7:222:8 | s1 | string.cpp:222:2:222:8 | ... = ... | |
| string.cpp:222:7:222:8 | s1 | string.cpp:223:7:223:8 | s5 | |
| string.cpp:222:7:222:8 | s1 | string.cpp:224:7:224:8 | s5 | |
| string.cpp:223:7:223:8 | ref arg s5 | string.cpp:224:7:224:8 | s5 | |
| string.cpp:223:7:223:8 | s5 | string.cpp:223:10:223:15 | call to insert | TAINT |
| string.cpp:223:20:223:21 | s2 | string.cpp:223:7:223:8 | ref arg s5 | TAINT |
| string.cpp:223:20:223:21 | s2 | string.cpp:223:10:223:15 | call to insert | TAINT |
| string.cpp:226:7:226:8 | s1 | string.cpp:226:2:226:8 | ... = ... | |
| string.cpp:226:7:226:8 | s1 | string.cpp:227:7:227:8 | s6 | |
| string.cpp:226:7:226:8 | s1 | string.cpp:228:7:228:8 | s6 | |
| string.cpp:227:7:227:8 | ref arg s6 | string.cpp:228:7:228:8 | s6 | |
| string.cpp:227:7:227:8 | s6 | string.cpp:227:10:227:15 | call to insert | TAINT |
| string.cpp:227:24:227:24 | c | string.cpp:227:7:227:8 | ref arg s6 | TAINT |
| string.cpp:227:24:227:24 | c | string.cpp:227:10:227:15 | call to insert | TAINT |
| string.cpp:232:17:232:23 | hello | string.cpp:232:17:232:24 | call to basic_string | TAINT |
| string.cpp:232:17:232:24 | call to basic_string | string.cpp:237:7:237:8 | s1 | |
| string.cpp:232:17:232:24 | call to basic_string | string.cpp:238:24:238:25 | s1 | |
| string.cpp:232:17:232:24 | call to basic_string | string.cpp:242:24:242:25 | s1 | |
| string.cpp:232:17:232:24 | call to basic_string | string.cpp:245:7:245:8 | s1 | |
| string.cpp:232:17:232:24 | call to basic_string | string.cpp:249:7:249:8 | s1 | |
| string.cpp:233:17:233:22 | call to source | string.cpp:233:17:233:25 | call to basic_string | TAINT |
| string.cpp:233:17:233:25 | call to basic_string | string.cpp:241:7:241:8 | s2 | |
| string.cpp:233:17:233:25 | call to basic_string | string.cpp:246:24:246:25 | s2 | |
| string.cpp:234:11:234:25 | call to source | string.cpp:250:28:250:28 | c | |
| string.cpp:237:7:237:8 | s1 | string.cpp:237:2:237:8 | ... = ... | |
| string.cpp:237:7:237:8 | s1 | string.cpp:238:7:238:8 | s3 | |
| string.cpp:237:7:237:8 | s1 | string.cpp:239:7:239:8 | s3 | |
| string.cpp:238:7:238:8 | ref arg s3 | string.cpp:239:7:239:8 | s3 | |
| string.cpp:238:7:238:8 | s3 | string.cpp:238:10:238:16 | call to replace | TAINT |
| string.cpp:238:24:238:25 | s1 | string.cpp:238:7:238:8 | ref arg s3 | TAINT |
| string.cpp:238:24:238:25 | s1 | string.cpp:238:10:238:16 | call to replace | TAINT |
| string.cpp:241:7:241:8 | s2 | string.cpp:241:2:241:8 | ... = ... | |
| string.cpp:241:7:241:8 | s2 | string.cpp:242:7:242:8 | s4 | |
| string.cpp:241:7:241:8 | s2 | string.cpp:243:7:243:8 | s4 | |
| string.cpp:242:7:242:8 | ref arg s4 | string.cpp:243:7:243:8 | s4 | |
| string.cpp:242:7:242:8 | s4 | string.cpp:242:10:242:16 | call to replace | TAINT |
| string.cpp:242:24:242:25 | s1 | string.cpp:242:7:242:8 | ref arg s4 | TAINT |
| string.cpp:242:24:242:25 | s1 | string.cpp:242:10:242:16 | call to replace | TAINT |
| string.cpp:245:7:245:8 | s1 | string.cpp:245:2:245:8 | ... = ... | |
| string.cpp:245:7:245:8 | s1 | string.cpp:246:7:246:8 | s5 | |
| string.cpp:245:7:245:8 | s1 | string.cpp:247:7:247:8 | s5 | |
| string.cpp:246:7:246:8 | ref arg s5 | string.cpp:247:7:247:8 | s5 | |
| string.cpp:246:7:246:8 | s5 | string.cpp:246:10:246:16 | call to replace | TAINT |
| string.cpp:246:24:246:25 | s2 | string.cpp:246:7:246:8 | ref arg s5 | TAINT |
| string.cpp:246:24:246:25 | s2 | string.cpp:246:10:246:16 | call to replace | TAINT |
| string.cpp:249:7:249:8 | s1 | string.cpp:249:2:249:8 | ... = ... | |
| string.cpp:249:7:249:8 | s1 | string.cpp:250:7:250:8 | s6 | |
| string.cpp:249:7:249:8 | s1 | string.cpp:251:7:251:8 | s6 | |
| string.cpp:250:7:250:8 | ref arg s6 | string.cpp:251:7:251:8 | s6 | |
| string.cpp:250:7:250:8 | s6 | string.cpp:250:10:250:16 | call to replace | TAINT |
| string.cpp:250:28:250:28 | c | string.cpp:250:7:250:8 | ref arg s6 | TAINT |
| string.cpp:250:28:250:28 | c | string.cpp:250:10:250:16 | call to replace | TAINT |
| string.cpp:255:17:255:20 | {...} | string.cpp:260:10:260:11 | b1 | |
| string.cpp:255:17:255:20 | {...} | string.cpp:261:7:261:8 | b1 | |
| string.cpp:255:19:255:19 | 0 | string.cpp:255:17:255:20 | {...} | TAINT |
| string.cpp:256:17:256:20 | {...} | string.cpp:263:10:263:11 | b2 | |
| string.cpp:256:17:256:20 | {...} | string.cpp:264:7:264:8 | b2 | |
| string.cpp:256:19:256:19 | 0 | string.cpp:256:17:256:20 | {...} | TAINT |
| string.cpp:257:17:257:23 | hello | string.cpp:257:17:257:24 | call to basic_string | TAINT |
| string.cpp:257:17:257:24 | call to basic_string | string.cpp:260:2:260:3 | s1 | |
| string.cpp:257:17:257:24 | call to basic_string | string.cpp:260:14:260:15 | s1 | |
| string.cpp:257:17:257:24 | call to basic_string | string.cpp:263:14:263:15 | s1 | |
| string.cpp:258:17:258:22 | call to source | string.cpp:258:17:258:25 | call to basic_string | TAINT |
| string.cpp:258:17:258:25 | call to basic_string | string.cpp:263:2:263:3 | s2 | |
| string.cpp:260:2:260:3 | s1 | string.cpp:260:10:260:11 | ref arg b1 | TAINT |
| string.cpp:260:10:260:11 | ref arg b1 | string.cpp:261:7:261:8 | b1 | |
| string.cpp:263:2:263:3 | s2 | string.cpp:263:10:263:11 | ref arg b2 | TAINT |
| string.cpp:263:10:263:11 | ref arg b2 | string.cpp:264:7:264:8 | b2 | |
| string.cpp:268:17:268:23 | hello | string.cpp:268:17:268:24 | call to basic_string | TAINT |
| string.cpp:268:17:268:24 | call to basic_string | string.cpp:273:7:273:8 | s1 | |
| string.cpp:268:17:268:24 | call to basic_string | string.cpp:278:2:278:3 | s1 | |
| string.cpp:268:17:268:24 | call to basic_string | string.cpp:281:7:281:8 | s1 | |
| string.cpp:269:17:269:22 | call to source | string.cpp:269:17:269:25 | call to basic_string | TAINT |
| string.cpp:269:17:269:25 | call to basic_string | string.cpp:274:7:274:8 | s2 | |
| string.cpp:269:17:269:25 | call to basic_string | string.cpp:278:10:278:11 | s2 | |
| string.cpp:269:17:269:25 | call to basic_string | string.cpp:282:7:282:8 | s2 | |
| string.cpp:270:17:270:23 | world | string.cpp:270:17:270:24 | call to basic_string | TAINT |
| string.cpp:270:17:270:24 | call to basic_string | string.cpp:275:7:275:8 | s3 | |
| string.cpp:270:17:270:24 | call to basic_string | string.cpp:279:10:279:11 | s3 | |
| string.cpp:270:17:270:24 | call to basic_string | string.cpp:283:7:283:8 | s3 | |
| string.cpp:271:17:271:22 | call to source | string.cpp:271:17:271:25 | call to basic_string | TAINT |
| string.cpp:271:17:271:25 | call to basic_string | string.cpp:276:7:276:8 | s4 | |
| string.cpp:271:17:271:25 | call to basic_string | string.cpp:279:2:279:3 | s4 | |
| string.cpp:271:17:271:25 | call to basic_string | string.cpp:284:7:284:8 | s4 | |
| string.cpp:278:2:278:3 | ref arg s1 | string.cpp:281:7:281:8 | s1 | |
| string.cpp:278:2:278:3 | s1 | string.cpp:278:10:278:11 | ref arg s2 | TAINT |
| string.cpp:278:10:278:11 | ref arg s2 | string.cpp:282:7:282:8 | s2 | |
| string.cpp:278:10:278:11 | s2 | string.cpp:278:2:278:3 | ref arg s1 | TAINT |
| string.cpp:279:2:279:3 | ref arg s4 | string.cpp:284:7:284:8 | s4 | |
| string.cpp:279:2:279:3 | s4 | string.cpp:279:10:279:11 | ref arg s3 | TAINT |
| string.cpp:279:10:279:11 | ref arg s3 | string.cpp:283:7:283:8 | s3 | |
| string.cpp:279:10:279:11 | s3 | string.cpp:279:2:279:3 | ref arg s4 | TAINT |
| string.cpp:288:17:288:22 | call to source | string.cpp:288:17:288:25 | call to basic_string | TAINT |
| string.cpp:288:17:288:25 | call to basic_string | string.cpp:292:7:292:8 | s1 | |
| string.cpp:288:17:288:25 | call to basic_string | string.cpp:296:2:296:3 | s1 | |
| string.cpp:288:17:288:25 | call to basic_string | string.cpp:300:7:300:8 | s1 | |
| string.cpp:289:17:289:22 | call to source | string.cpp:289:17:289:25 | call to basic_string | TAINT |
| string.cpp:289:17:289:25 | call to basic_string | string.cpp:293:7:293:8 | s2 | |
| string.cpp:290:17:290:22 | call to source | string.cpp:290:17:290:25 | call to basic_string | TAINT |
| string.cpp:290:17:290:25 | call to basic_string | string.cpp:294:7:294:8 | s3 | |
| string.cpp:290:17:290:25 | call to basic_string | string.cpp:298:7:298:8 | s3 | |
| string.cpp:296:2:296:3 | ref arg s1 | string.cpp:300:7:300:8 | s1 | |
| string.cpp:297:7:297:8 | | string.cpp:297:7:297:8 | call to basic_string | TAINT |
| string.cpp:297:7:297:8 | call to basic_string | string.cpp:297:2:297:8 | ... = ... | |
| string.cpp:297:7:297:8 | call to basic_string | string.cpp:301:7:301:8 | s2 | |
| string.cpp:298:7:298:8 | s3 | string.cpp:298:2:298:8 | ... = ... | |
| string.cpp:298:7:298:8 | s3 | string.cpp:302:7:302:8 | s3 | |
| string.cpp:307:16:307:20 | 123 | string.cpp:307:16:307:21 | call to basic_string | TAINT |
| string.cpp:307:16:307:21 | call to basic_string | string.cpp:310:7:310:7 | a | |
| string.cpp:307:16:307:21 | call to basic_string | string.cpp:312:7:312:7 | a | |
| string.cpp:308:16:308:21 | call to source | string.cpp:308:16:308:24 | call to basic_string | TAINT |
| string.cpp:308:16:308:24 | call to basic_string | string.cpp:311:7:311:7 | b | |
| string.cpp:308:16:308:24 | call to basic_string | string.cpp:313:7:313:7 | b | |
| string.cpp:310:7:310:7 | a | string.cpp:310:9:310:12 | call to data | TAINT |
| string.cpp:310:7:310:7 | ref arg a | string.cpp:312:7:312:7 | a | |
| string.cpp:311:7:311:7 | b | string.cpp:311:9:311:12 | call to data | TAINT |
| string.cpp:311:7:311:7 | ref arg b | string.cpp:313:7:313:7 | b | |
| string.cpp:318:16:318:20 | 123 | string.cpp:318:16:318:21 | call to basic_string | TAINT |
| string.cpp:318:16:318:21 | call to basic_string | string.cpp:321:7:321:7 | a | |
| string.cpp:318:16:318:21 | call to basic_string | string.cpp:321:19:321:19 | a | |
| string.cpp:319:16:319:21 | call to source | string.cpp:319:16:319:24 | call to basic_string | TAINT |
| string.cpp:319:16:319:24 | call to basic_string | string.cpp:322:7:322:7 | b | |
| string.cpp:319:16:319:24 | call to basic_string | string.cpp:322:19:322:19 | b | |
| string.cpp:321:7:321:7 | a | string.cpp:321:9:321:14 | call to substr | TAINT |
| string.cpp:322:7:322:7 | b | string.cpp:322:9:322:14 | call to substr | TAINT |
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:16:2:16:4 | ss1 | |
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:22:7:22:9 | ss1 | |
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:27:7:27:9 | ss1 | |

View File

@@ -39,11 +39,14 @@ namespace std
class basic_string {
public:
typedef typename Allocator::size_type size_type;
static const size_type npos = -1;
explicit basic_string(const Allocator& a = Allocator());
basic_string(const charT* s, const Allocator& a = Allocator());
const charT* c_str() const;
charT* data() noexcept;
size_t length() const;
typedef std::iterator<random_access_iterator_tag, charT> iterator;
typedef std::iterator<random_access_iterator_tag, const charT> const_iterator;
@@ -60,6 +63,16 @@ namespace std
basic_string& append(const basic_string& str);
basic_string& append(const charT* s);
basic_string& append(size_type n, charT c);
basic_string& assign(const basic_string& str);
basic_string& assign(size_type n, charT c);
basic_string& insert(size_type pos, const basic_string& str);
basic_string& insert(size_type pos, size_type n, charT c);
basic_string& replace(size_type pos1, size_type n1, const basic_string& str);
basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c);
size_type copy(charT* s, size_type n, size_type pos = 0) const;
void clear() noexcept;
basic_string substr(size_type pos = 0, size_type n = npos) const;
void swap(basic_string& s) noexcept/*(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value)*/;
};
template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs);

View File

@@ -184,3 +184,140 @@ void test_string_append() {
sink(s10); // tainted
}
}
void test_string_assign() {
std::string s1("hello");
std::string s2(source());
char c = ns_char::source();
std::string s3, s4, s5;
std::string s6(source());
sink(s3.assign(s1));
sink(s3);
sink(s4.assign(s2)); // tainted
sink(s4); // tainted
sink(s5.assign(10, c)); // tainted
sink(s5); // tainted
sink(s6.assign(s1));
sink(s6); // [FALSE POSITIVE]
}
void test_string_insert() {
std::string s1("hello");
std::string s2(source());
char c = ns_char::source();
std::string s3, s4, s5, s6;
s3 = s1;
sink(s3.insert(0, s1));
sink(s3);
s4 = s2;
sink(s4.insert(0, s1)); // tainted
sink(s4); // tainted
s5 = s1;
sink(s5.insert(0, s2)); // tainted
sink(s5); // tainted
s6 = s1;
sink(s6.insert(0, 10, c)); // tainted
sink(s6); // tainted
}
void test_string_replace() {
std::string s1("hello");
std::string s2(source());
char c = ns_char::source();
std::string s3, s4, s5, s6;
s3 = s1;
sink(s3.replace(1, 2, s1));
sink(s3);
s4 = s2;
sink(s4.replace(1, 2, s1)); // tainted
sink(s4); // tainted
s5 = s1;
sink(s5.replace(1, 2, s2)); // tainted
sink(s5); // tainted
s6 = s1;
sink(s6.replace(1, 2, 10, c)); // tainted
sink(s6); // tainted
}
void test_string_copy() {
char b1[1024] = {0};
char b2[1024] = {0};
std::string s1("hello");
std::string s2(source());
s1.copy(b1, s1.length(), 0);
sink(b1);
s2.copy(b2, s1.length(), 0);
sink(b2); // tainted
}
void test_string_swap() {
std::string s1("hello");
std::string s2(source());
std::string s3("world");
std::string s4(source());
sink(s1);
sink(s2); // tainted
sink(s3);
sink(s4); // tainted
s1.swap(s2);
s4.swap(s3);
sink(s1); // tainted
sink(s2); // [FALSE POSITIVE]
sink(s3); // tainted
sink(s4); // [FALSE POSITIVE]
}
void test_string_clear() {
std::string s1(source());
std::string s2(source());
std::string s3(source());
sink(s1); // tainted
sink(s2); // tainted
sink(s3); // tainted
s1.clear();
s2 = "";
s3 = s3;
sink(s1); // [FALSE POSITIVE]
sink(s2);
sink(s3); // tainted
}
void test_string_data()
{
std::string a("123");
std::string b(source());
sink(a.data());
sink(b.data()); // tainted
sink(a.length());
sink(b.length());
}
void test_string_substr()
{
std::string a("123");
std::string b(source());
sink(a.substr(0, a.length()));
sink(b.substr(0, b.length())); // tainted
}

View File

@@ -60,6 +60,37 @@
| string.cpp:171:8:171:9 | s8 | string.cpp:154:18:154:23 | call to source |
| string.cpp:176:8:176:9 | s9 | string.cpp:174:13:174:18 | call to source |
| string.cpp:184:8:184:10 | s10 | string.cpp:181:12:181:26 | call to source |
| string.cpp:198:10:198:15 | call to assign | string.cpp:190:17:190:22 | call to source |
| string.cpp:199:7:199:8 | s4 | string.cpp:190:17:190:22 | call to source |
| string.cpp:201:10:201:15 | call to assign | string.cpp:191:11:191:25 | call to source |
| string.cpp:202:7:202:8 | s5 | string.cpp:191:11:191:25 | call to source |
| string.cpp:205:7:205:8 | s6 | string.cpp:193:17:193:22 | call to source |
| string.cpp:219:10:219:15 | call to insert | string.cpp:210:17:210:22 | call to source |
| string.cpp:220:7:220:8 | s4 | string.cpp:210:17:210:22 | call to source |
| string.cpp:223:10:223:15 | call to insert | string.cpp:210:17:210:22 | call to source |
| string.cpp:224:7:224:8 | s5 | string.cpp:210:17:210:22 | call to source |
| string.cpp:227:10:227:15 | call to insert | string.cpp:211:11:211:25 | call to source |
| string.cpp:228:7:228:8 | s6 | string.cpp:211:11:211:25 | call to source |
| string.cpp:242:10:242:16 | call to replace | string.cpp:233:17:233:22 | call to source |
| string.cpp:243:7:243:8 | s4 | string.cpp:233:17:233:22 | call to source |
| string.cpp:246:10:246:16 | call to replace | string.cpp:233:17:233:22 | call to source |
| string.cpp:247:7:247:8 | s5 | string.cpp:233:17:233:22 | call to source |
| string.cpp:250:10:250:16 | call to replace | string.cpp:234:11:234:25 | call to source |
| string.cpp:251:7:251:8 | s6 | string.cpp:234:11:234:25 | call to source |
| string.cpp:264:7:264:8 | b2 | string.cpp:258:17:258:22 | call to source |
| string.cpp:274:7:274:8 | s2 | string.cpp:269:17:269:22 | call to source |
| string.cpp:276:7:276:8 | s4 | string.cpp:271:17:271:22 | call to source |
| string.cpp:281:7:281:8 | s1 | string.cpp:269:17:269:22 | call to source |
| string.cpp:282:7:282:8 | s2 | string.cpp:269:17:269:22 | call to source |
| string.cpp:283:7:283:8 | s3 | string.cpp:271:17:271:22 | call to source |
| string.cpp:284:7:284:8 | s4 | string.cpp:271:17:271:22 | call to source |
| string.cpp:292:7:292:8 | s1 | string.cpp:288:17:288:22 | call to source |
| string.cpp:293:7:293:8 | s2 | string.cpp:289:17:289:22 | call to source |
| string.cpp:294:7:294:8 | s3 | string.cpp:290:17:290:22 | call to source |
| string.cpp:300:7:300:8 | s1 | string.cpp:288:17:288:22 | call to source |
| string.cpp:302:7:302:8 | s3 | string.cpp:290:17:290:22 | call to source |
| string.cpp:311:9:311:12 | call to data | string.cpp:308:16:308:21 | call to source |
| string.cpp:322:9:322:14 | call to substr | string.cpp:319:16:319:21 | call to source |
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
| structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source |

View File

@@ -57,6 +57,37 @@
| string.cpp:171:8:171:9 | string.cpp:154:18:154:23 | AST only |
| string.cpp:176:8:176:9 | string.cpp:174:13:174:18 | AST only |
| string.cpp:184:8:184:10 | string.cpp:181:12:181:26 | AST only |
| string.cpp:198:10:198:15 | string.cpp:190:17:190:22 | AST only |
| string.cpp:199:7:199:8 | string.cpp:190:17:190:22 | AST only |
| string.cpp:201:10:201:15 | string.cpp:191:11:191:25 | AST only |
| string.cpp:202:7:202:8 | string.cpp:191:11:191:25 | AST only |
| string.cpp:205:7:205:8 | string.cpp:193:17:193:22 | AST only |
| string.cpp:219:10:219:15 | string.cpp:210:17:210:22 | AST only |
| string.cpp:220:7:220:8 | string.cpp:210:17:210:22 | AST only |
| string.cpp:223:10:223:15 | string.cpp:210:17:210:22 | AST only |
| string.cpp:224:7:224:8 | string.cpp:210:17:210:22 | AST only |
| string.cpp:227:10:227:15 | string.cpp:211:11:211:25 | AST only |
| string.cpp:228:7:228:8 | string.cpp:211:11:211:25 | AST only |
| string.cpp:242:10:242:16 | string.cpp:233:17:233:22 | AST only |
| string.cpp:243:7:243:8 | string.cpp:233:17:233:22 | AST only |
| string.cpp:246:10:246:16 | string.cpp:233:17:233:22 | AST only |
| string.cpp:247:7:247:8 | string.cpp:233:17:233:22 | AST only |
| string.cpp:250:10:250:16 | string.cpp:234:11:234:25 | AST only |
| string.cpp:251:7:251:8 | string.cpp:234:11:234:25 | AST only |
| string.cpp:264:7:264:8 | string.cpp:258:17:258:22 | AST only |
| string.cpp:274:7:274:8 | string.cpp:269:17:269:22 | AST only |
| string.cpp:276:7:276:8 | string.cpp:271:17:271:22 | AST only |
| string.cpp:281:7:281:8 | string.cpp:269:17:269:22 | AST only |
| string.cpp:282:7:282:8 | string.cpp:269:17:269:22 | AST only |
| string.cpp:283:7:283:8 | string.cpp:271:17:271:22 | AST only |
| string.cpp:284:7:284:8 | string.cpp:271:17:271:22 | AST only |
| string.cpp:292:7:292:8 | string.cpp:288:17:288:22 | AST only |
| string.cpp:293:7:293:8 | string.cpp:289:17:289:22 | AST only |
| string.cpp:294:7:294:8 | string.cpp:290:17:290:22 | AST only |
| string.cpp:300:7:300:8 | string.cpp:288:17:288:22 | AST only |
| string.cpp:302:7:302:8 | string.cpp:290:17:290:22 | AST only |
| string.cpp:311:9:311:12 | string.cpp:308:16:308:21 | AST only |
| string.cpp:322:9:322:14 | string.cpp:319:16:319:21 | AST only |
| structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only |
| structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only |
| structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only |

View File

@@ -291,7 +291,7 @@ struct A {
Point *NewAliasing(int x) {
Point* p = new Point;
Point* q = new Point;
int j = new A(new A(x))->i;
int j = (new A(new A(x)))->i;
A* a = new A;
return p;
}
@@ -310,4 +310,4 @@ class ThisAliasTest {
void setX(int arg) {
this->x = arg;
}
};
};

View File

@@ -98,7 +98,7 @@
| test.c:150:25:150:26 | x3 | -2147483648 |
| test.c:150:30:150:31 | c0 | -128 |
| test.c:150:35:150:36 | s0 | 0 |
| test.c:154:11:154:11 | x | -9223372036854776000 |
| test.c:154:11:154:11 | x | -9223372036854775808 |
| test.c:154:20:154:20 | x | 1 |
| test.c:154:30:154:30 | x | 1 |
| test.c:154:35:154:35 | x | 1 |
@@ -492,7 +492,7 @@
| test.c:478:3:478:4 | xy | 0 |
| test.c:478:8:478:8 | x | 274177 |
| test.c:478:12:478:12 | y | 67280421310721 |
| test.c:479:10:479:11 | xy | 18446744073709552000 |
| test.c:479:10:479:11 | xy | 18446744073709551616 |
| test.c:483:7:483:8 | ui | 0 |
| test.c:484:43:484:44 | ui | 10 |
| test.c:484:48:484:49 | ui | 10 |
@@ -501,6 +501,37 @@
| test.c:488:28:488:29 | ul | 10 |
| test.c:488:33:488:34 | ul | 10 |
| test.c:489:12:489:17 | result | 0 |
| test.c:495:7:495:8 | ui | 0 |
| test.c:495:19:495:20 | ui | 0 |
| test.c:496:5:496:6 | ui | 2 |
| test.c:496:11:496:12 | ui | 2 |
| test.c:497:12:497:13 | ui | 4 |
| test.c:501:3:501:9 | uiconst | 10 |
| test.c:504:3:504:9 | ulconst | 10 |
| test.c:505:10:505:16 | uiconst | 40 |
| test.c:505:20:505:26 | ulconst | 40 |
| test.c:509:7:509:7 | i | -2147483648 |
| test.c:509:18:509:18 | i | -1 |
| test.c:510:5:510:5 | i | -2147483648 |
| test.c:510:13:510:13 | i | -1 |
| test.c:511:9:511:9 | i | -5 |
| test.c:513:5:513:5 | i | -2147483648 |
| test.c:513:9:513:9 | i | -5 |
| test.c:514:9:514:9 | i | -30 |
| test.c:516:5:516:5 | i | -30 |
| test.c:517:9:517:9 | i | -210 |
| test.c:519:5:519:5 | i | -210 |
| test.c:520:9:520:9 | i | -1155 |
| test.c:522:7:522:7 | i | -2147483648 |
| test.c:523:5:523:5 | i | -2147483648 |
| test.c:523:9:523:9 | i | -1 |
| test.c:524:9:524:9 | i | 1 |
| test.c:526:3:526:3 | i | -2147483648 |
| test.c:526:7:526:7 | i | -2147483648 |
| test.c:527:10:527:10 | i | -2147483648 |
| test.c:530:3:530:3 | i | -2147483648 |
| test.c:530:10:530:11 | sc | 1 |
| test.c:532:7:532:7 | i | -128 |
| test.cpp:10:7:10:7 | b | -2147483648 |
| test.cpp:11:5:11:5 | x | -2147483648 |
| test.cpp:13:10:13:10 | x | -2147483648 |

View File

@@ -476,13 +476,13 @@ unsigned long mult_overflow() {
x = 274177UL;
y = 67280421310721UL;
xy = x * y;
return xy; // BUG: lower bound should be <= 18446744073709551617UL
return xy; // BUG: upper bound should be >= 18446744073709551617UL
}
unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) {
if (ui >= 10) {
unsigned long result = (unsigned long)ui * ui;
return result; // BUG: upper bound should be >= 18446744065119617025 (possibly a pretty-printing bug)
return result; // BUG: upper bound should be >= 18446744065119617025
}
if (ul >= 10) {
unsigned long result = ul * ul;
@@ -490,3 +490,46 @@ unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) {
}
return 0;
}
unsigned long mul_assign(unsigned int ui) {
if (ui <= 10 && ui >= 2) {
ui *= ui + 0;
return ui; // 4 .. 100
}
unsigned int uiconst = 10;
uiconst *= 4;
unsigned long ulconst = 10;
ulconst *= 4;
return uiconst + ulconst; // 40 .. 40 for both
}
int mul_by_constant(int i, int j) {
if (i >= -1 && i <= 2) {
i = 5 * i;
out(i); // -5 .. 10
i = i * -3;
out(i); // -30 .. 15
i *= 7;
out(i); // -210 .. 105
i *= -11;
out(i); // -1155 .. 2310
}
if (i == -1) {
i = i * (int)0xffFFffFF; // fully converted literal is -1
out(i); // 1 .. 1
}
i = i * -1;
out( i); // -2^31 .. 2^31-1
signed char sc = 1;
i = (*&sc *= 2);
out(sc); // demonstrate that we couldn't analyze the LHS of the `*=` above...
out(i); // -128 .. 127 // ... but we can still bound its result by its type.
return 0;
}

View File

@@ -73,10 +73,10 @@
| test.c:105:5:105:5 | c | 127 |
| test.c:106:9:106:9 | c | 127 |
| test.c:109:9:109:9 | c | 127 |
| test.c:119:10:119:10 | n | 18446744073709552000 |
| test.c:124:11:124:15 | Start | 18446744073709552000 |
| test.c:127:6:127:10 | Start | 18446744073709552000 |
| test.c:127:15:127:20 | Length | 18446744073709552000 |
| test.c:119:10:119:10 | n | 18446744073709551616 |
| test.c:124:11:124:15 | Start | 18446744073709551616 |
| test.c:127:6:127:10 | Start | 18446744073709551616 |
| test.c:127:15:127:20 | Length | 18446744073709551616 |
| test.c:135:22:135:22 | c | 127 |
| test.c:137:20:137:20 | x | 0 |
| test.c:138:11:138:11 | i | 2147483647 |
@@ -98,9 +98,9 @@
| test.c:150:25:150:26 | x3 | 2147483647 |
| test.c:150:30:150:31 | c0 | 127 |
| test.c:150:35:150:36 | s0 | 65535 |
| test.c:154:11:154:11 | x | 9223372036854776000 |
| test.c:154:20:154:20 | x | 9223372036854776000 |
| test.c:154:30:154:30 | x | 9223372036854776000 |
| test.c:154:11:154:11 | x | 9223372036854775808 |
| test.c:154:20:154:20 | x | 9223372036854775808 |
| test.c:154:30:154:30 | x | 9223372036854775808 |
| test.c:154:35:154:35 | x | 2147483647 |
| test.c:161:12:161:12 | a | 2147483647 |
| test.c:161:17:161:17 | a | 2147483647 |
@@ -481,26 +481,57 @@
| test.c:461:5:461:9 | total | 506 |
| test.c:461:14:461:14 | r | 253 |
| test.c:464:10:464:14 | total | 759 |
| test.c:469:3:469:3 | x | 18446744073709552000 |
| test.c:469:7:469:7 | y | 18446744073709552000 |
| test.c:470:3:470:4 | xy | 18446744073709552000 |
| test.c:469:3:469:3 | x | 18446744073709551616 |
| test.c:469:7:469:7 | y | 18446744073709551616 |
| test.c:470:3:470:4 | xy | 18446744073709551616 |
| test.c:470:8:470:8 | x | 1000000003 |
| test.c:470:12:470:12 | y | 1000000003 |
| test.c:471:10:471:11 | xy | 1000000006000000000 |
| test.c:476:3:476:3 | x | 18446744073709552000 |
| test.c:477:3:477:3 | y | 18446744073709552000 |
| test.c:478:3:478:4 | xy | 18446744073709552000 |
| test.c:476:3:476:3 | x | 18446744073709551616 |
| test.c:477:3:477:3 | y | 18446744073709551616 |
| test.c:478:3:478:4 | xy | 18446744073709551616 |
| test.c:478:8:478:8 | x | 274177 |
| test.c:478:12:478:12 | y | 67280421310721 |
| test.c:479:10:479:11 | xy | 18446744073709552000 |
| test.c:479:10:479:11 | xy | 18446744073709551616 |
| test.c:483:7:483:8 | ui | 4294967295 |
| test.c:484:43:484:44 | ui | 4294967295 |
| test.c:484:48:484:49 | ui | 4294967295 |
| test.c:485:12:485:17 | result | 18446744065119617000 |
| test.c:487:7:487:8 | ul | 18446744073709552000 |
| test.c:488:28:488:29 | ul | 18446744073709552000 |
| test.c:488:33:488:34 | ul | 18446744073709552000 |
| test.c:489:12:489:17 | result | 18446744073709552000 |
| test.c:485:12:485:17 | result | 18446744065119617024 |
| test.c:487:7:487:8 | ul | 18446744073709551616 |
| test.c:488:28:488:29 | ul | 18446744073709551616 |
| test.c:488:33:488:34 | ul | 18446744073709551616 |
| test.c:489:12:489:17 | result | 18446744073709551616 |
| test.c:495:7:495:8 | ui | 4294967295 |
| test.c:495:19:495:20 | ui | 10 |
| test.c:496:5:496:6 | ui | 10 |
| test.c:496:11:496:12 | ui | 10 |
| test.c:497:12:497:13 | ui | 100 |
| test.c:501:3:501:9 | uiconst | 10 |
| test.c:504:3:504:9 | ulconst | 10 |
| test.c:505:10:505:16 | uiconst | 40 |
| test.c:505:20:505:26 | ulconst | 40 |
| test.c:509:7:509:7 | i | 2147483647 |
| test.c:509:18:509:18 | i | 2147483647 |
| test.c:510:5:510:5 | i | 2147483647 |
| test.c:510:13:510:13 | i | 2 |
| test.c:511:9:511:9 | i | 10 |
| test.c:513:5:513:5 | i | 2147483647 |
| test.c:513:9:513:9 | i | 10 |
| test.c:514:9:514:9 | i | 15 |
| test.c:516:5:516:5 | i | 15 |
| test.c:517:9:517:9 | i | 105 |
| test.c:519:5:519:5 | i | 105 |
| test.c:520:9:520:9 | i | 2310 |
| test.c:522:7:522:7 | i | 2147483647 |
| test.c:523:5:523:5 | i | 2147483647 |
| test.c:523:9:523:9 | i | -1 |
| test.c:524:9:524:9 | i | 1 |
| test.c:526:3:526:3 | i | 2147483647 |
| test.c:526:7:526:7 | i | 2147483647 |
| test.c:527:10:527:10 | i | 2147483647 |
| test.c:530:3:530:3 | i | 2147483647 |
| test.c:530:10:530:11 | sc | 1 |
| test.c:532:7:532:7 | i | 127 |
| test.cpp:10:7:10:7 | b | 2147483647 |
| test.cpp:11:5:11:5 | x | 2147483647 |
| test.cpp:13:10:13:10 | x | 2147483647 |

View File

@@ -43,8 +43,8 @@
| PointlessComparison.c:383:6:383:17 | ... >= ... | Comparison is always false because ... & ... <= 2. |
| PointlessComparison.c:388:10:388:21 | ... > ... | Comparison is always false because ... * ... <= 408. |
| PointlessComparison.c:391:12:391:20 | ... < ... | Comparison is always false because ... * ... >= 6. |
| PointlessComparison.c:414:7:414:16 | ... == ... | Comparison is always false because ... * ... >= 18446744073709552000. |
| PointlessComparison.cpp:36:6:36:33 | ... >= ... | Comparison is always false because ... >> ... <= 9223372036854776000. |
| PointlessComparison.c:414:7:414:16 | ... == ... | Comparison is always false because ... * ... >= 18446744073709551616. |
| PointlessComparison.cpp:36:6:36:33 | ... >= ... | Comparison is always false because ... >> ... <= 9223372036854775808. |
| PointlessComparison.cpp:41:6:41:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. |
| PointlessComparison.cpp:42:6:42:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. |
| PointlessComparison.cpp:43:6:43:29 | ... >= ... | Comparison is always true because ... >> ... >= 140737488355327.5. |

View File

@@ -2,5 +2,8 @@
| test3.c:13:16:13:19 | * ... | $@ flows to here and is used in an expression which might overflow negatively. | test3.c:11:15:11:18 | argv | User-provided value |
| test4.cpp:13:17:13:20 | access to array | $@ flows to here and is used in an expression which might overflow negatively. | test4.cpp:9:13:9:16 | argv | User-provided value |
| test5.cpp:10:9:10:15 | call to strtoul | $@ flows to here and is used in an expression which might overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:17:6:17:27 | ... * ... | $@ flows to here and is used in an expression which might overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test5.cpp:19:6:19:13 | ... * ... | $@ flows to here and is used in an expression which might overflow. | test5.cpp:9:7:9:9 | buf | User-provided value |
| test.c:14:15:14:35 | ... * ... | $@ flows to here and is used in an expression which might overflow. | test.c:11:29:11:32 | argv | User-provided value |
| test.c:44:7:44:12 | ... -- | $@ flows to here and is used in an expression which might overflow negatively. | test.c:41:17:41:20 | argv | User-provided value |
| test.c:54:7:54:12 | ... -- | $@ flows to here and is used in an expression which might overflow negatively. | test.c:51:17:51:20 | argv | User-provided value |

3
csharp/.gitignore vendored
View File

@@ -10,4 +10,5 @@ csharp.log
**/bin/Release
*.tlog
.vs
*.user
*.user
.vscode/launch.json

View File

@@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
protected abstract ArrayTypeSyntax TypeSyntax { get; }
public abstract InitializerExpressionSyntax Initializer { get; }
public abstract InitializerExpressionSyntax Initializer { get; }
protected override void PopulateExpression(TextWriter trapFile)
{
@@ -48,7 +48,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
ExprKind.INT_LITERAL,
this,
child,
false,
true,
size.ToString());
new Expression(info);

View File

@@ -80,7 +80,7 @@ namespace Semmle.Extraction.CSharp.Entities
else
Expression.Create(Context, expr, this, 0);
Context.NumberOfLines(trapFile, symbol, this);
Context.NumberOfLines(trapFile, BodyDeclaringSymbol, this);
});
}
@@ -126,7 +126,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
trapFile.Write('<');
// Encode the nullability of the type arguments in the label.
// Type arguments with different nullability can result in
// Type arguments with different nullability can result in
// a constructed method with different nullability of its parameters and return type,
// so we need to create a distinct database entity for it.
trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); trapFile.Write((int)ta.Nullability); });

View File

@@ -13,6 +13,8 @@ namespace Semmle.Extraction.CSharp.Entities
public override string Name => symbol.GetName();
protected override IMethodSymbol BodyDeclaringSymbol => symbol.PartialImplementationPart ?? symbol;
public IMethodSymbol SourceDeclaration
{
get

View File

@@ -95,14 +95,15 @@ namespace Semmle.Extraction.CSharp.Entities
Context.BindComments(this, FullLocation);
}
protected virtual T BodyDeclaringSymbol => symbol;
public BlockSyntax Block
{
get
{
return symbol.
return BodyDeclaringSymbol.
DeclaringSyntaxReferences.
Select(r => r.GetSyntax()).
SelectMany(n => n.ChildNodes()).
SelectMany(r => r.GetSyntax().ChildNodes()).
OfType<BlockSyntax>().
FirstOrDefault();
}
@@ -112,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
get
{
return symbol.
return BodyDeclaringSymbol.
DeclaringSyntaxReferences.
SelectMany(r => r.GetSyntax().ChildNodes()).
OfType<ArrowExpressionClauseSyntax>().

28
csharp/ql/src/printAst.ql Normal file
View File

@@ -0,0 +1,28 @@
/**
* @name Print AST
* @description Outputs a representation of a file's Abstract Syntax Tree. This
* query is used by the VS Code extension.
* @id csharp/print-ast
* @kind graph
* @tags ide-contextual-queries/print-ast
*/
import csharp
import semmle.code.csharp.PrintAst
import definitions
/**
* The source file to generate an AST from.
*/
external string selectedSourceFile();
class PrintAstConfigurationOverride extends PrintAstConfiguration {
/**
* Holds if the location matches the selected file in the VS Code extension and
* the element is `fromSource`.
*/
override predicate shouldPrint(Element e, Location l) {
super.shouldPrint(e, l) and
l.getFile() = getEncodedFile(selectedSourceFile())
}
}

View File

@@ -93,4 +93,6 @@ class Attribute extends TopLevelExprParent, @attribute {
result = "[" + name + "(...)]"
)
}
override string getAPrimaryQlClass() { result = "Attribute" }
}

View File

@@ -284,6 +284,8 @@ class Method extends Callable, Virtualizable, Attributable, @method {
override Parameter getRawParameter(int i) {
if this.isStatic() then result = this.getParameter(i) else result = this.getParameter(i - 1)
}
override string getAPrimaryQlClass() { result = "Method" }
}
/**
@@ -302,6 +304,8 @@ class ExtensionMethod extends Method {
/** Gets the type being extended by this method. */
Type getExtendedType() { result = getParameter(0).getType() }
override string getAPrimaryQlClass() { result = "ExtensionMethod" }
}
/**
@@ -371,6 +375,8 @@ class StaticConstructor extends Constructor {
StaticConstructor() { this.isStatic() }
override string getUndecoratedName() { result = ".cctor" }
override string getAPrimaryQlClass() { result = "StaticConstructor" }
}
/**
@@ -385,6 +391,8 @@ class StaticConstructor extends Constructor {
*/
class InstanceConstructor extends Constructor {
InstanceConstructor() { not this.isStatic() }
override string getAPrimaryQlClass() { result = "InstanceConstructor" }
}
/**
@@ -413,6 +421,8 @@ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @de
override Location getALocation() { destructor_location(this, result) }
override string toString() { result = Callable.super.toString() }
override string getAPrimaryQlClass() { result = "Destructor" }
}
/**
@@ -471,6 +481,8 @@ class PlusOperator extends UnaryOperator {
PlusOperator() { this.getName() = "+" }
override string getFunctionName() { result = "op_UnaryPlus" }
override string getAPrimaryQlClass() { result = "PlusOperator" }
}
/**
@@ -486,6 +498,8 @@ class MinusOperator extends UnaryOperator {
MinusOperator() { this.getName() = "-" }
override string getFunctionName() { result = "op_UnaryNegation" }
override string getAPrimaryQlClass() { result = "MinusOperator" }
}
/**
@@ -501,6 +515,8 @@ class NotOperator extends UnaryOperator {
NotOperator() { this.getName() = "!" }
override string getFunctionName() { result = "op_LogicalNot" }
override string getAPrimaryQlClass() { result = "NotOperator" }
}
/**
@@ -516,6 +532,8 @@ class ComplementOperator extends UnaryOperator {
ComplementOperator() { this.getName() = "~" }
override string getFunctionName() { result = "op_OnesComplement" }
override string getAPrimaryQlClass() { result = "ComplementOperator" }
}
/**
@@ -531,6 +549,8 @@ class IncrementOperator extends UnaryOperator {
IncrementOperator() { this.getName() = "++" }
override string getFunctionName() { result = "op_Increment" }
override string getAPrimaryQlClass() { result = "IncrementOperator" }
}
/**
@@ -546,6 +566,8 @@ class DecrementOperator extends UnaryOperator {
DecrementOperator() { this.getName() = "--" }
override string getFunctionName() { result = "op_Decrement" }
override string getAPrimaryQlClass() { result = "DecrementOperator" }
}
/**
@@ -561,6 +583,8 @@ class FalseOperator extends UnaryOperator {
FalseOperator() { this.getName() = "false" }
override string getFunctionName() { result = "op_False" }
override string getAPrimaryQlClass() { result = "FalseOperator" }
}
/**
@@ -576,6 +600,8 @@ class TrueOperator extends UnaryOperator {
TrueOperator() { this.getName() = "true" }
override string getFunctionName() { result = "op_True" }
override string getAPrimaryQlClass() { result = "TrueOperator" }
}
/**
@@ -608,6 +634,8 @@ class AddOperator extends BinaryOperator {
AddOperator() { this.getName() = "+" }
override string getFunctionName() { result = "op_Addition" }
override string getAPrimaryQlClass() { result = "AddOperator" }
}
/**
@@ -623,6 +651,8 @@ class SubOperator extends BinaryOperator {
SubOperator() { this.getName() = "-" }
override string getFunctionName() { result = "op_Subtraction" }
override string getAPrimaryQlClass() { result = "SubOperator" }
}
/**
@@ -638,6 +668,8 @@ class MulOperator extends BinaryOperator {
MulOperator() { this.getName() = "*" }
override string getFunctionName() { result = "op_Multiply" }
override string getAPrimaryQlClass() { result = "MulOperator" }
}
/**
@@ -653,6 +685,8 @@ class DivOperator extends BinaryOperator {
DivOperator() { this.getName() = "/" }
override string getFunctionName() { result = "op_Division" }
override string getAPrimaryQlClass() { result = "DivOperator" }
}
/**
@@ -668,6 +702,8 @@ class RemOperator extends BinaryOperator {
RemOperator() { this.getName() = "%" }
override string getFunctionName() { result = "op_Modulus" }
override string getAPrimaryQlClass() { result = "RemOperator" }
}
/**
@@ -683,6 +719,8 @@ class AndOperator extends BinaryOperator {
AndOperator() { this.getName() = "&" }
override string getFunctionName() { result = "op_BitwiseAnd" }
override string getAPrimaryQlClass() { result = "AndOperator" }
}
/**
@@ -698,6 +736,8 @@ class OrOperator extends BinaryOperator {
OrOperator() { this.getName() = "|" }
override string getFunctionName() { result = "op_BitwiseOr" }
override string getAPrimaryQlClass() { result = "OrOperator" }
}
/**
@@ -713,6 +753,8 @@ class XorOperator extends BinaryOperator {
XorOperator() { this.getName() = "^" }
override string getFunctionName() { result = "op_ExclusiveOr" }
override string getAPrimaryQlClass() { result = "XorOperator" }
}
/**
@@ -728,6 +770,8 @@ class LShiftOperator extends BinaryOperator {
LShiftOperator() { this.getName() = "<<" }
override string getFunctionName() { result = "op_LeftShift" }
override string getAPrimaryQlClass() { result = "LShiftOperator" }
}
/**
@@ -743,6 +787,8 @@ class RShiftOperator extends BinaryOperator {
RShiftOperator() { this.getName() = ">>" }
override string getFunctionName() { result = "op_RightShift" }
override string getAPrimaryQlClass() { result = "RShiftOperator" }
}
/**
@@ -758,6 +804,8 @@ class EQOperator extends BinaryOperator {
EQOperator() { this.getName() = "==" }
override string getFunctionName() { result = "op_Equality" }
override string getAPrimaryQlClass() { result = "EQOperator" }
}
/**
@@ -773,6 +821,8 @@ class NEOperator extends BinaryOperator {
NEOperator() { this.getName() = "!=" }
override string getFunctionName() { result = "op_Inequality" }
override string getAPrimaryQlClass() { result = "NEOperator" }
}
/**
@@ -788,6 +838,8 @@ class LTOperator extends BinaryOperator {
LTOperator() { this.getName() = "<" }
override string getFunctionName() { result = "op_LessThan" }
override string getAPrimaryQlClass() { result = "LTOperator" }
}
/**
@@ -803,6 +855,8 @@ class GTOperator extends BinaryOperator {
GTOperator() { this.getName() = ">" }
override string getFunctionName() { result = "op_GreaterThan" }
override string getAPrimaryQlClass() { result = "GTOperator" }
}
/**
@@ -818,6 +872,8 @@ class LEOperator extends BinaryOperator {
LEOperator() { this.getName() = "<=" }
override string getFunctionName() { result = "op_LessThanOrEqual" }
override string getAPrimaryQlClass() { result = "LEOperator" }
}
/**
@@ -833,6 +889,8 @@ class GEOperator extends BinaryOperator {
GEOperator() { this.getName() = ">=" }
override string getFunctionName() { result = "op_GreaterThanOrEqual" }
override string getAPrimaryQlClass() { result = "GEOperator" }
}
/**
@@ -870,6 +928,8 @@ class ImplicitConversionOperator extends ConversionOperator {
ImplicitConversionOperator() { this.getName() = "implicit conversion" }
override string getFunctionName() { result = "op_Implicit" }
override string getAPrimaryQlClass() { result = "ImplicitConversionOperator" }
}
/**
@@ -885,6 +945,8 @@ class ExplicitConversionOperator extends ConversionOperator {
ExplicitConversionOperator() { this.getName() = "explicit conversion" }
override string getFunctionName() { result = "op_Explicit" }
override string getAPrimaryQlClass() { result = "ExplicitConversionOperator" }
}
/**
@@ -923,4 +985,6 @@ class LocalFunction extends Callable, Modifiable, @local_function {
override Location getALocation() { result = getStatement().getALocation() }
override Parameter getRawParameter(int i) { result = getParameter(i) }
override string getAPrimaryQlClass() { result = "LocalFunction" }
}

View File

@@ -48,4 +48,17 @@ class Element extends DotNet::Element, @element {
* other children (zero-based).
*/
int getIndex() { exists(Element parent | parent.getChild(result) = this) }
/**
* Gets the name of a primary CodeQL class to which this element belongs.
*
* For most elements, this is simply the most precise syntactic category to
* which they belong; for example, `AddExpr` is a primary class, but
* `BinaryOperation` is not.
*
* This predicate always has a result. If no primary class can be
* determined, the result is `"???"`. If multiple primary classes match,
* this predicate can have multiple results.
*/
string getAPrimaryQlClass() { result = "???" }
}

View File

@@ -61,6 +61,8 @@ class Event extends DeclarationWithAccessors, @event {
}
override Location getALocation() { event_location(this, result) }
override string getAPrimaryQlClass() { result = "Event" }
}
/**
@@ -107,6 +109,8 @@ class EventAccessor extends Accessor, @event_accessor {
*/
class AddEventAccessor extends EventAccessor, @add_event_accessor {
override string getName() { result = "add" + "_" + getDeclaration().getName() }
override string getAPrimaryQlClass() { result = "AddEventAccessor" }
}
/**
@@ -124,4 +128,6 @@ class AddEventAccessor extends EventAccessor, @add_event_accessor {
*/
class RemoveEventAccessor extends EventAccessor, @remove_event_accessor {
override string getName() { result = "remove" + "_" + getDeclaration().getName() }
override string getAPrimaryQlClass() { result = "RemoveEventAccessor" }
}

View File

@@ -183,6 +183,8 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
/** Gets the generic that defines this type parameter. */
UnboundGeneric getGeneric() { type_parameters(this, _, result, _) }
override string getAPrimaryQlClass() { result = "TypeParameter" }
}
/**

View File

@@ -259,7 +259,7 @@ private module Gvn {
private newtype TGvnType =
TLeafGvnType(LeafType t) or
TMethodTypeParameterGvnType(int i) { i = any(MethodTypeParameter p).getIndex() } or
TConstructedGvnType(ConstructedGvnTypeList l)
TConstructedGvnType(ConstructedGvnTypeList l) { l.isFullyConstructed() }
private newtype TConstructedGvnTypeList =
TConstructedGvnTypeNil(Unification::CompoundTypeKind k) or
@@ -334,6 +334,10 @@ private module Gvn {
)
}
predicate isFullyConstructed() {
this.getKind().getNumberOfTypeParameters() - 1 = this.length()
}
private GvnType getArg(int i) {
exists(GvnType head, ConstructedGvnTypeList tail |
this = TConstructedGvnTypeCons(head, tail)
@@ -345,47 +349,71 @@ private module Gvn {
)
}
private Unification::GenericType getConstructedGenericDeclaringTypeAt(int i) {
i = 0 and
result = this.getKind().getConstructedSourceDeclaration()
or
result = this.getConstructedGenericDeclaringTypeAt(i - 1).getGenericDeclaringType()
}
private predicate isDeclaringTypeAt(int i) {
exists(this.getConstructedGenericDeclaringTypeAt(i - 1))
}
/**
* Gets a textual representation of this constructed type, restricted
* to the prefix `t` of the underlying source declaration type.
*
* The `toString()` calculation needs to be split up into prefixes, in
* order to apply the type arguments correctly. For example, a source
* declaration type `A<>.B.C<,>` applied to types `int, string, bool`
* needs to be printed as `A<int>.B.C<string,bool>`.
* Gets the `j`th `toString()` part of the `i`th nested component of this
* constructed type, if any. The nested components are sorted in reverse
* order, while the individual parts are sorted in normal order.
*/
language[monotonicAggregates]
private string toStringConstructed(Unification::GenericType t) {
t = this.getKind().getConstructedSourceDeclaration().getGenericDeclaringType*() and
exists(int offset, int children, string name, string nameArgs |
offset = t.getNumberOfDeclaringArguments() and
children = t.getNumberOfArgumentsSelf() and
name = Unification::getNameNested(t) and
if children = 0
then nameArgs = name
else
exists(string offsetArgs |
offsetArgs =
concat(int i |
i in [offset .. offset + children - 1]
|
this.getArg(i).toString(), "," order by i
) and
nameArgs = name.prefix(name.length() - children - 1) + "<" + offsetArgs + ">"
private string toStringConstructedPart(int i, int j) {
this.isFullyConstructed() and
exists(Unification::GenericType t |
t = this.getConstructedGenericDeclaringTypeAt(i) and
exists(int offset, int children, string name |
offset = t.getNumberOfDeclaringArguments() and
children = t.getNumberOfArgumentsSelf() and
name = Unification::getNameNested(t) and
if children = 0
then
j = 0 and result = name
or
this.isDeclaringTypeAt(i) and j = 1 and result = "."
else (
j = 0 and result = name.prefix(name.length() - children - 1) + "<"
or
j in [1 .. 2 * children - 1] and
if j % 2 = 0
then result = ","
else result = this.getArg((j + 1) / 2 + offset - 1).toString()
or
j = 2 * children and
result = ">"
or
this.isDeclaringTypeAt(i) and
j = 2 * children + 1 and
result = "."
)
|
offset = 0 and result = nameArgs
or
result = this.toStringConstructed(t.getGenericDeclaringType()) + "." + nameArgs
)
)
}
language[monotonicAggregates]
string toString() {
this.isFullyConstructed() and
exists(Unification::CompoundTypeKind k | k = this.getKind() |
result = k.toStringBuiltin(this.getArg(0).toString())
or
result = this.toStringConstructed(k.getConstructedSourceDeclaration())
result =
strictconcat(int i, int j |
exists(Unification::GenericType t, int children |
t = this.getConstructedGenericDeclaringTypeAt(i) and
children = t.getNumberOfArgumentsSelf() and
if children = 0 then j = 0 else j in [0 .. 2 * children]
)
|
this.toStringConstructedPart(i, j) order by i desc, j
)
)
}

View File

@@ -207,4 +207,6 @@ class NamespaceDeclaration extends Element, @namespace_declaration {
override Location getALocation() { namespace_declaration_location(this, result) }
override string toString() { result = "namespace ... { ... }" }
override string getAPrimaryQlClass() { result = "NamespaceDeclaration" }
}

View File

@@ -0,0 +1,20 @@
/**
* @name Print AST
* @description Outputs a representation of the Abstract Syntax Tree.
* @id csharp/print-ast
* @kind graph
*/
import csharp
import PrintAst
/**
* Temporarily tweak this class or make a copy to control which functions are
* printed.
*/
class PrintAstConfigurationOverride extends PrintAstConfiguration {
/**
* TWEAK THIS PREDICATE AS NEEDED.
*/
override predicate shouldPrint(Element e, Location l) { super.shouldPrint(e, l) }
}

View File

@@ -0,0 +1,620 @@
/**
* Provides queries to pretty-print a C# AST as a graph.
*
* By default, this will print the AST for all elements in the database. To change this behavior,
* extend `PrintAstConfiguration` and override `shouldPrint` to hold for only the elements
* you wish to view the AST for.
*/
import csharp
private newtype TPrintAstConfiguration = MkPrintAstConfiguration()
/**
* The query can extend this class to control which elements are printed.
*/
class PrintAstConfiguration extends TPrintAstConfiguration {
/**
* Gets a textual representation of this `PrintAstConfiguration`.
*/
string toString() { result = "PrintAstConfiguration" }
/**
* Controls whether the `Element` should be considered for AST printing.
* By default it checks whether the `Element` `e` belongs to `Location` `l`.
*/
predicate shouldPrint(Element e, Location l) { e.fromSource() and l = e.getLocation() }
}
private predicate shouldPrint(Element e, Location l) {
exists(PrintAstConfiguration config | config.shouldPrint(e, l))
}
private predicate isImplicitExpression(ControlFlowElement element) {
element.(Expr).isImplicit() and not exists(element.getAChild())
}
private predicate isFilteredCompilerGenerated(Declaration d) {
d.isCompilerGenerated() and
not d instanceof Accessor
}
private predicate isNotNeeded(Element e) {
isFilteredCompilerGenerated(e)
or
e instanceof ConstructedGeneric
or
e instanceof AnonymousClass
or
isNotNeeded(e.(Declaration).getDeclaringType())
or
isNotNeeded(e.(Parameter).getDeclaringElement())
or
isNotNeeded(e.(Attribute).getTarget())
}
/**
* Retrieves the canonical QL class(es) for entity `el`
*/
private string getQlClass(Element el) {
result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] "
// Alternative implementation -- do not delete. It is useful for QL class discovery.
// result = "["+ concat(el.getAQlClass(), ",") + "] "
}
/**
* An `Element`, such as a `namespace` and a `partial class`, might have multiple locations.
* The locations are ordered by line, column, and then the first one is selected.
*/
private Location getRepresentativeLocation(Element ast) {
result =
min(Location loc |
shouldPrint(ast, loc)
|
loc order by loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn()
)
}
private predicate locationSortKeys(Element ast, string file, int line, int column) {
exists(Location loc |
loc = getRepresentativeLocation(ast) and
file = loc.getFile().toString() and
line = loc.getStartLine() and
column = loc.getStartColumn()
)
or
not exists(getRepresentativeLocation(ast)) and
file = "" and
line = 0 and
column = 0
}
private predicate hasInterestingBaseTypes(ValueOrRefType type) {
exists(getAnInterestingBaseType(type))
}
private ValueOrRefType getAnInterestingBaseType(ValueOrRefType type) {
not type instanceof TupleType and
not type instanceof ArrayType and
not type instanceof NullableType and
result = type.getABaseType() and
isInterestingBaseType(result)
}
private predicate isInterestingBaseType(ValueOrRefType base) {
not base instanceof ObjectType and
not base.getQualifiedName() = "System.ValueType" and
not base.getQualifiedName() = "System.Delegate" and
not base.getQualifiedName() = "System.MulticastDelegate" and
not base.getQualifiedName() = "System.Enum"
}
/**
* Printed AST nodes are mostly `Element`s of the underlying AST.
* There are extra AST nodes generated for parameters of `Parameterizable`s,
* attributes of `Attributable`s, type parameters of `UnboundGeneric` and
* base types of `ValueOrRefType` declarations. These extra nodes are used
* as containers to organize the tree a bit better.
*/
private newtype TPrintAstNode =
TElementNode(Element element) { shouldPrint(element, _) } or
TParametersNode(Parameterizable parameterizable) {
shouldPrint(parameterizable, _) and
parameterizable.getNumberOfParameters() > 0 and
not isNotNeeded(parameterizable)
} or
TAttributesNode(Attributable attributable) {
shouldPrint(attributable, _) and
exists(attributable.getAnAttribute()) and
not isNotNeeded(attributable)
} or
TTypeParametersNode(UnboundGeneric unboundGeneric) {
shouldPrint(unboundGeneric, _) and
unboundGeneric.getNumberOfTypeParameters() > 0 and
not isNotNeeded(unboundGeneric)
} or
TBaseTypesNode(ValueOrRefType type) {
shouldPrint(type, _) and
hasInterestingBaseTypes(type) and
not isNotNeeded(type)
} or
TBaseTypeNode(ValueOrRefType derived, ValueOrRefType base) {
shouldPrint(derived, _) and
base = getAnInterestingBaseType(derived) and
not isNotNeeded(derived)
}
/**
* A node in the output tree.
*/
class PrintAstNode extends TPrintAstNode {
/**
* Gets a textual representation of this node in the PrintAst output tree.
*/
abstract string toString();
/**
* Gets the child node at index `childIndex`. Child indices must be unique,
* but need not be contiguous.
*/
abstract PrintAstNode getChild(int childIndex);
/**
* Gets a child of this node.
*/
final PrintAstNode getAChild() { result = getChild(_) }
/**
* Gets the parent of this node, if any.
*/
final PrintAstNode getParent() { result.getAChild() = this }
/**
* Gets the location of this node in the source code.
*/
abstract Location getLocation();
/**
* Gets the value of the property of this node, where the name of the property
* is `key`.
*/
string getProperty(string key) {
key = "semmle.label" and
result = toString()
}
/**
* Gets the label for the edge from this node to the specified child. By
* default, this is just the index of the child, but subclasses can override
* this.
*/
string getChildEdgeLabel(int childIndex) {
exists(getChild(childIndex)) and
result = childIndex.toString()
}
}
/**
* A node representing an AST node with an underlying `Element`.
*/
abstract class ElementNode extends PrintAstNode, TElementNode {
Element element;
ElementNode() { this = TElementNode(element) }
override string toString() { result = getQlClass(element) + element.toString() }
override Location getLocation() { result = getRepresentativeLocation(element) }
/**
* Gets the `Element` represented by this node.
*/
final Element getElement() { result = element }
}
/**
* A node representing a `ControlFlowElement` (`Expr` or `Stmt`).
*/
class ControlFlowElementNode extends ElementNode {
ControlFlowElement controlFlowElement;
ControlFlowElementNode() {
controlFlowElement = element and
// Removing implicit expressions
not isImplicitExpression(element) and
// Removing extra nodes that are generated for an `AssignOperation`
not exists(AssignOperation ao |
ao.hasExpandedAssignment() and
(
ao.getExpandedAssignment() = controlFlowElement or
ao.getExpandedAssignment().getRValue() = controlFlowElement or
ao.getExpandedAssignment().getRValue().(BinaryOperation).getLeftOperand() =
controlFlowElement.getParent*() or
ao.getExpandedAssignment().getRValue().(OperatorCall).getChild(0) =
controlFlowElement.getParent*()
)
) and
not isNotNeeded(element.getParent+())
}
override ElementNode getChild(int childIndex) {
result.getElement() = controlFlowElement.getChild(childIndex)
}
}
/**
* A node representing a `LocalFunctionStmt`.
* Each `LocalFunction` is displayed below its corresponding `LocalFunctionStmt`.
*/
final class LocalFunctionStmtNode extends ControlFlowElementNode {
LocalFunctionStmt stmt;
LocalFunctionStmtNode() { stmt = element }
override CallableNode getChild(int childIndex) {
childIndex = 0 and
result.getElement() = stmt.getLocalFunction()
}
}
/**
* A node representing a `Callable`, such as method declaration.
*/
final class CallableNode extends ElementNode {
Callable callable;
CallableNode() {
callable = element and
not isNotNeeded(callable)
}
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and
result.(AttributesNode).getAttributable() = callable
or
childIndex = 1 and
result.(TypeParametersNode).getUnboundGeneric() = callable
or
childIndex = 2 and
result.(ParametersNode).getParameterizable() = callable
or
childIndex = 3 and
result.(ElementNode).getElement() = callable.(Constructor).getInitializer()
or
childIndex = 4 and
result.(ElementNode).getElement() = callable.getBody()
}
}
/**
* A node representing a `DeclarationWithAccessors`, such as property declaration.
*/
final class DeclarationWithAccessorsNode extends ElementNode {
DeclarationWithAccessors declaration;
DeclarationWithAccessorsNode() {
declaration = element and
not isNotNeeded(declaration.getDeclaringType())
}
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and
result.(AttributesNode).getAttributable() = declaration
or
childIndex = 1 and
result.(ParametersNode).getParameterizable() = declaration
or
childIndex = 2 and
result.(ElementNode).getElement() = declaration.(Property).getInitializer().getParent()
or
result.(ElementNode).getElement() =
rank[childIndex - 2](Element a, string file, int line, int column |
a = declaration.getAnAccessor() and
locationSortKeys(a, file, line, column)
|
a order by file, line, column
)
}
}
/**
* A node representing a `Field` declaration.
*/
final class FieldNode extends ElementNode {
Field field;
FieldNode() {
field = element and
not field.getDeclaringType() instanceof TupleType and
not isNotNeeded(field.getDeclaringType())
}
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and
result.(AttributesNode).getAttributable() = field
or
childIndex = 1 and
field.hasInitializer() and
(
if field.getDeclaringType() instanceof Enum
then result.(ElementNode).getElement() = field.getInitializer()
else result.(ElementNode).getElement() = field.getInitializer().getParent()
)
}
}
/**
* A node representing a `Parameter` declaration.
*/
final class ParameterNode extends ElementNode {
Parameter param;
ParameterNode() {
param = element and
not isNotNeeded(param.getDeclaringElement())
}
override Location getLocation() {
not param.hasExtensionMethodModifier() and result = super.getLocation()
or
// for extension method first parameters, we're choosing the shorter location of the two
param.hasExtensionMethodModifier() and
result =
min(Location loc |
shouldPrint(param, loc) and
loc.getStartLine() = loc.getEndLine()
|
loc order by loc.getEndColumn() - loc.getStartColumn()
)
}
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and
result.(AttributesNode).getAttributable() = param
or
childIndex = 1 and
result.(ElementNode).getElement() = param.getDefaultValue()
}
}
/**
* A node representing an `Attribute`.
*/
final class AttributeNode extends ElementNode {
Attribute attr;
AttributeNode() {
attr = element and
not isNotNeeded(attr.getTarget())
}
override ElementNode getChild(int childIndex) { result.getElement() = attr.getChild(childIndex) }
}
/**
* A node representing a `TypeParameter`.
*/
final class TypeParameterNode extends ElementNode {
TypeParameter typeParameter;
TypeParameterNode() {
typeParameter = element and
not isNotNeeded(typeParameter.getDeclaringGeneric())
}
override ElementNode getChild(int childIndex) { none() }
}
/**
* A node representing a `ValueOrRefType`.
*/
final class TypeNode extends ElementNode {
ValueOrRefType type;
TypeNode() {
type = element and
not type instanceof TupleType and
not type instanceof ArrayType and
not type instanceof NullableType and
not isNotNeeded(type)
}
override PrintAstNode getChild(int childIndex) {
childIndex = 0 and
result.(AttributesNode).getAttributable() = type
or
childIndex = 1 and
result.(TypeParametersNode).getUnboundGeneric() = type
or
childIndex = 2 and
result.(ParametersNode).getParameterizable() = type
or
childIndex = 3 and
result.(BaseTypesNode).getValueOrRefType() = type
or
result.(ElementNode).getElement() =
rank[childIndex - 3](Member m, string file, int line, int column |
m = type.getAMember() and
locationSortKeys(m, file, line, column)
|
m order by file, line, column
)
}
}
/**
* A node representing a `NamespaceDeclaration`.
*/
final class NamespaceNode extends ElementNode {
NamespaceDeclaration namespace;
NamespaceNode() { namespace = element }
override PrintAstNode getChild(int childIndex) {
result.(ElementNode).getElement() =
rank[childIndex](Element a, string file, int line, int column |
(a = namespace.getAChildNamespaceDeclaration() or a = namespace.getATypeDeclaration()) and
locationSortKeys(a, file, line, column)
|
a order by file, line, column
)
}
}
/**
* A node representing the parameters of a `Parameterizable`.
* Only rendered if there's at least one parameter and if the
* `Parameterizable` is not compiler generated or is of type
* `Accessor`.
*/
final class ParametersNode extends PrintAstNode, TParametersNode {
Parameterizable parameterizable;
ParametersNode() { this = TParametersNode(parameterizable) }
override string toString() { result = "(Parameters)" }
override Location getLocation() { none() }
override ParameterNode getChild(int childIndex) {
result.getElement() = parameterizable.getParameter(childIndex)
}
/**
* Gets the underlying `Parameterizable`
*/
Parameterizable getParameterizable() { result = parameterizable }
}
/**
* A node representing the attributes of an `Attributable`.
* Only rendered if there's at least one attribute.
*/
final class AttributesNode extends PrintAstNode, TAttributesNode {
Attributable attributable;
AttributesNode() { this = TAttributesNode(attributable) }
override string toString() { result = "(Attributes)" }
override Location getLocation() { none() }
override AttributeNode getChild(int childIndex) {
result.getElement() =
rank[childIndex](Attribute a, string file, int line, int column |
a = attributable.getAnAttribute() and
locationSortKeys(a, file, line, column)
|
a order by file, line, column
)
}
/**
* Gets the underlying `Attributable`
*/
Attributable getAttributable() { result = attributable }
}
/**
* A node representing the type parameters of an `UnboundGeneric`.
*/
final class TypeParametersNode extends PrintAstNode, TTypeParametersNode {
UnboundGeneric unboundGeneric;
TypeParametersNode() { this = TTypeParametersNode(unboundGeneric) }
override string toString() { result = "(Type parameters)" }
override Location getLocation() { none() }
override TypeParameterNode getChild(int childIndex) {
result.getElement() = unboundGeneric.getTypeParameter(childIndex)
}
/**
* Gets the underlying `UnboundGeneric`
*/
UnboundGeneric getUnboundGeneric() { result = unboundGeneric }
}
/**
* A node representing the base types of a `ValueOrRefType`.
*/
final class BaseTypesNode extends PrintAstNode, TBaseTypesNode {
ValueOrRefType valueOrRefType;
BaseTypesNode() { this = TBaseTypesNode(valueOrRefType) }
override string toString() { result = "(Base types)" }
override Location getLocation() { none() }
override BaseTypeNode getChild(int childIndex) {
childIndex = 0 and
result.getBaseType() = valueOrRefType.getBaseClass() and
result.getDerivedType() = valueOrRefType
or
result.getBaseType() =
rank[childIndex](ValueOrRefType base, string name |
base = valueOrRefType.getABaseInterface() and
name = base.toString()
|
base order by name
) and
result.getDerivedType() = valueOrRefType
}
/**
* Gets the underlying `ValueOrRefType`
*/
ValueOrRefType getValueOrRefType() { result = valueOrRefType }
}
/**
* A node representing a base type reference of a `ValueOrRefType` declaration.
*/
final class BaseTypeNode extends PrintAstNode, TBaseTypeNode {
ValueOrRefType derived;
ValueOrRefType base;
BaseTypeNode() { this = TBaseTypeNode(derived, base) }
override string toString() { result = getQlClass(base) + base.toString() }
override Location getLocation() { result = derived.getLocation() }
override BaseTypeNode getChild(int childIndex) { none() }
/**
* Gets the underlying derived `ValueOrRefType`
*/
ValueOrRefType getDerivedType() { result = derived }
/**
* Gets the underlying base `ValueOrRefType`
*/
ValueOrRefType getBaseType() { result = base }
}
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
query predicate nodes(PrintAstNode node, string key, string value) { value = node.getProperty(key) }
/**
* Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the
* given `value`.
*/
query predicate edges(PrintAstNode source, PrintAstNode target, string key, string value) {
exists(int childIndex |
target = source.getChild(childIndex) and
(
key = "semmle.label" and value = source.getChildEdgeLabel(childIndex)
or
key = "semmle.order" and value = childIndex.toString()
)
)
}
/** Holds if property `key` of the graph has the given `value`. */
query predicate graphProperties(string key, string value) {
key = "semmle.graphKind" and value = "tree"
}

View File

@@ -232,6 +232,8 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper
override Getter getGetter() { result = DeclarationWithGetSetAccessors.super.getGetter() }
override Setter getSetter() { result = DeclarationWithGetSetAccessors.super.getSetter() }
override string getAPrimaryQlClass() { result = "Property" }
}
/**
@@ -298,6 +300,8 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer
override Location getALocation() { indexer_location(this, result) }
override string toStringWithTypes() { result = getName() + "[" + parameterTypesToString() + "]" }
override string getAPrimaryQlClass() { result = "Indexer" }
}
/**
@@ -415,6 +419,8 @@ class Getter extends Accessor, @getter {
override DeclarationWithGetSetAccessors getDeclaration() {
result = Accessor.super.getDeclaration()
}
override string getAPrimaryQlClass() { result = "Getter" }
}
/**
@@ -464,6 +470,8 @@ class Setter extends Accessor, @setter {
override DeclarationWithGetSetAccessors getDeclaration() {
result = Accessor.super.getDeclaration()
}
override string getAPrimaryQlClass() { result = "Setter" }
}
/**
@@ -554,4 +562,6 @@ class IndexerProperty extends Property {
// ```
result.getIndexer() = i
}
override string getAPrimaryQlClass() { result = "IndexerProperty" }
}

View File

@@ -76,6 +76,8 @@ class BlockStmt extends Stmt, @block_stmt {
}
override string toString() { result = "{...}" }
override string getAPrimaryQlClass() { result = "BlockStmt" }
}
/**
@@ -96,6 +98,8 @@ class ExprStmt extends Stmt, @expr_stmt {
Expr getExpr() { result.getParent() = this }
override string toString() { result = "...;" }
override string getAPrimaryQlClass() { result = "ExprStmt" }
}
/**
@@ -131,6 +135,8 @@ class IfStmt extends SelectionStmt, @if_stmt {
Stmt getElse() { result = this.getChild(2) }
override string toString() { result = "if (...) ..." }
override string getAPrimaryQlClass() { result = "IfStmt" }
}
/**
@@ -180,6 +186,8 @@ class SwitchStmt extends SelectionStmt, Switch, @switch_stmt {
override string toString() { result = "switch (...) {...}" }
override string getAPrimaryQlClass() { result = "SwitchStmt" }
/**
* Gets the `i`th statement in the body of this `switch` statement.
*
@@ -284,6 +292,8 @@ class CaseStmt extends Case, @case_stmt {
SwitchStmt getSwitchStmt() { result.getACase() = this }
override string toString() { result = "case ...:" }
override string getAPrimaryQlClass() { result = "CaseStmt" }
}
/**
@@ -305,6 +315,8 @@ class ConstCase extends CaseStmt, LabeledStmt {
override string getLabel() { result = p.getValue() }
override string toString() { result = CaseStmt.super.toString() }
override string getAPrimaryQlClass() { result = "ConstCase" }
}
/**
@@ -324,6 +336,8 @@ class DefaultCase extends CaseStmt, LabeledStmt {
override string getLabel() { result = "default" }
override string toString() { result = "default:" }
override string getAPrimaryQlClass() { result = "DefaultCase" }
}
/**
@@ -354,6 +368,8 @@ class WhileStmt extends LoopStmt, @while_stmt {
override Expr getCondition() { result.getParent() = this }
override string toString() { result = "while (...) ..." }
override string getAPrimaryQlClass() { result = "WhileStmt" }
}
/**
@@ -370,6 +386,8 @@ class DoStmt extends LoopStmt, @do_stmt {
override Expr getCondition() { result.getParent() = this }
override string toString() { result = "do ... while (...);" }
override string getAPrimaryQlClass() { result = "DoStmt" }
}
/**
@@ -440,6 +458,8 @@ class ForStmt extends LoopStmt, @for_stmt {
Expr getUpdate(int n) { exists(int i | result = this.getChild(i) and n = i - 1 and i >= 1) }
override string toString() { result = "for (...;...;...) ..." }
override string getAPrimaryQlClass() { result = "ForStmt" }
}
/**
@@ -562,6 +582,8 @@ class ForeachStmt extends LoopStmt, @foreach_stmt {
Expr getIterableExpr() { result = this.getChild(1) }
override string toString() { result = "foreach (... ... in ...) ..." }
override string getAPrimaryQlClass() { result = "ForeachStmt" }
}
/**
@@ -586,6 +608,8 @@ class JumpStmt extends Stmt, @jump_stmt { }
*/
class BreakStmt extends JumpStmt, @break_stmt {
override string toString() { result = "break;" }
override string getAPrimaryQlClass() { result = "BreakStmt" }
}
/**
@@ -602,6 +626,8 @@ class BreakStmt extends JumpStmt, @break_stmt {
*/
class ContinueStmt extends JumpStmt, @continue_stmt {
override string toString() { result = "continue;" }
override string getAPrimaryQlClass() { result = "ContinueStmt" }
}
/**
@@ -637,6 +663,8 @@ class GotoLabelStmt extends GotoStmt, @goto_stmt {
result.getEnclosingCallable() = getEnclosingCallable() and
result.getLabel() = getLabel()
}
override string getAPrimaryQlClass() { result = "GotoLabelStmt" }
}
/**
@@ -662,6 +690,8 @@ class GotoCaseStmt extends GotoStmt, @goto_case_stmt {
override string getLabel() { result = getExpr().getValue() }
override string toString() { result = "goto case ...;" }
override string getAPrimaryQlClass() { result = "GotoCaseStmt" }
}
/**
@@ -684,6 +714,8 @@ class GotoDefaultStmt extends GotoStmt, @goto_default_stmt {
override string toString() { result = "goto default;" }
override string getLabel() { result = "default" }
override string getAPrimaryQlClass() { result = "GotoDefaultStmt" }
}
/**
@@ -714,6 +746,8 @@ class ThrowStmt extends JumpStmt, ThrowElement, @throw_stmt {
result = mid.getParent()
)
}
override string getAPrimaryQlClass() { result = "ThrowStmt" }
}
/**
@@ -738,6 +772,8 @@ class ReturnStmt extends JumpStmt, @return_stmt {
Expr getExpr() { result.getParent() = this }
override string toString() { result = "return ...;" }
override string getAPrimaryQlClass() { result = "ReturnStmt" }
}
/**
@@ -769,6 +805,8 @@ class YieldBreakStmt extends YieldStmt {
YieldBreakStmt() { not exists(this.getExpr()) }
override string toString() { result = "yield break;" }
override string getAPrimaryQlClass() { result = "YieldBreakStmt" }
}
/**
@@ -789,6 +827,8 @@ class YieldReturnStmt extends YieldStmt {
YieldReturnStmt() { exists(this.getExpr()) }
override string toString() { result = "yield return ...;" }
override string getAPrimaryQlClass() { result = "YieldReturnStmt" }
}
/**
@@ -824,6 +864,8 @@ class TryStmt extends Stmt, @try_stmt {
override string toString() { result = "try {...} ..." }
override string getAPrimaryQlClass() { result = "TryStmt" }
/** Gets the `catch` clause that handles an exception of type `ex`, if any. */
CatchClause getAnExceptionHandler(ExceptionClass ex) { result = clauseHandlesException(ex, 0) }
@@ -965,6 +1007,8 @@ class SpecificCatchClause extends CatchClause {
LocalVariableDeclExpr getVariableDeclExpr() { result.getParent() = this }
override string toString() { result = "catch (...) {...}" }
override string getAPrimaryQlClass() { result = "SpecificCatchClause" }
}
/**
@@ -985,6 +1029,8 @@ class GeneralCatchClause extends CatchClause {
GeneralCatchClause() { catch_type(this, _, 2) }
override string toString() { result = "catch {...}" }
override string getAPrimaryQlClass() { result = "GeneralCatchClause" }
}
/**
@@ -1002,6 +1048,8 @@ class CheckedStmt extends Stmt, @checked_stmt {
BlockStmt getBlock() { result.getParent() = this }
override string toString() { result = "checked {...}" }
override string getAPrimaryQlClass() { result = "CheckedStmt" }
}
/**
@@ -1019,6 +1067,8 @@ class UncheckedStmt extends Stmt, @unchecked_stmt {
BlockStmt getBlock() { result.getParent() = this }
override string toString() { result = "unchecked {...}" }
override string getAPrimaryQlClass() { result = "UncheckedStmt" }
}
/**
@@ -1056,6 +1106,8 @@ class LockStmt extends Stmt, @lock_stmt {
/** Gets the type `T` if this statement is of the form `lock(typeof(T)) { ... }`. */
Type getLockTypeObject() { result = getExpr().(TypeofExpr).getTypeAccess().getTarget() }
override string getAPrimaryQlClass() { result = "LockStmt" }
}
/**
@@ -1134,6 +1186,8 @@ class UsingBlockStmt extends UsingStmt, @using_block_stmt {
Stmt getBody() { result.getParent() = this }
override string toString() { result = "using (...) {...}" }
override string getAPrimaryQlClass() { result = "UsingBlockStmt" }
}
/**
@@ -1171,6 +1225,8 @@ class LocalVariableDeclStmt extends Stmt, @decl_stmt {
LocalVariableDeclExpr getVariableDeclExpr(int n) { result = this.getChild(n) }
override string toString() { result = "... ...;" }
override string getAPrimaryQlClass() { result = "LocalVariableDeclStmt" }
}
/**
@@ -1207,6 +1263,8 @@ class LocalConstantDeclStmt extends LocalVariableDeclStmt, @const_decl_stmt {
override LocalConstantDeclExpr getVariableDeclExpr(int n) { result = this.getChild(n) }
override string toString() { result = "const ... ...;" }
override string getAPrimaryQlClass() { result = "LocalConstantDeclStmt" }
}
/**
@@ -1228,6 +1286,8 @@ class UsingDeclStmt extends LocalVariableDeclStmt, UsingStmt, @using_decl_stmt {
}
override Expr getAnExpr() { result = this.getAVariableDeclExpr().getInitializer() }
override string getAPrimaryQlClass() { result = "UsingDeclStmt" }
}
/**
@@ -1241,6 +1301,8 @@ class UsingDeclStmt extends LocalVariableDeclStmt, UsingStmt, @using_decl_stmt {
*/
class EmptyStmt extends Stmt, @empty_stmt {
override string toString() { result = ";" }
override string getAPrimaryQlClass() { result = "EmptyStmt" }
}
/**
@@ -1260,6 +1322,8 @@ class UnsafeStmt extends Stmt, @unsafe_stmt {
BlockStmt getBlock() { result.getParent() = this }
override string toString() { result = "unsafe {...}" }
override string getAPrimaryQlClass() { result = "UnsafeStmt" }
}
/**
@@ -1291,6 +1355,8 @@ class FixedStmt extends Stmt, @fixed_stmt {
Stmt getBody() { result.getParent() = this }
override string toString() { result = "fixed(...) { ... }" }
override string getAPrimaryQlClass() { result = "FixedStmt" }
}
/**
@@ -1306,7 +1372,9 @@ class FixedStmt extends Stmt, @fixed_stmt {
* exit: ...
* ```
*/
class LabelStmt extends LabeledStmt, @label_stmt { }
class LabelStmt extends LabeledStmt, @label_stmt {
override string getAPrimaryQlClass() { result = "LabelStmt" }
}
/**
* A labeled statement.
@@ -1356,4 +1424,6 @@ class LocalFunctionStmt extends Stmt, @local_function_stmt {
LocalFunction getLocalFunction() { local_function_stmts(this, result) }
override string toString() { result = getLocalFunction().getName() + "(...)" }
override string getAPrimaryQlClass() { result = "LocalFunctionStmt" }
}

View File

@@ -648,6 +648,8 @@ class Enum extends ValueType, @enum_type {
EnumConstant getEnumConstant(string value) {
result = this.getAnEnumConstant() and result.getValue() = value
}
override string getAPrimaryQlClass() { result = "Enum" }
}
/**
@@ -665,6 +667,8 @@ class Struct extends ValueType, @struct_type {
/** Holds if this `struct` has a `readonly` modifier. */
predicate isReadonly() { hasModifier("readonly") }
override string getAPrimaryQlClass() { result = "Struct" }
}
/**
@@ -713,7 +717,9 @@ private predicate isNonOverridden(Member m) { not m.(Virtualizable).isOverridden
* }
* ```
*/
class Class extends RefType, @class_type { }
class Class extends RefType, @class_type {
override string getAPrimaryQlClass() { result = "Class" }
}
/**
* A class generated by the compiler from an anonymous object creation.
@@ -755,7 +761,9 @@ class StringType extends Class {
* }
* ```
*/
class Interface extends RefType, @interface_type { }
class Interface extends RefType, @interface_type {
override string getAPrimaryQlClass() { result = "Interface" }
}
/**
* A `delegate` type, for example
@@ -770,6 +778,8 @@ class DelegateType extends RefType, Parameterizable, @delegate_type {
/** Gets the annotated return type of this delegate. */
AnnotatedType getAnnotatedReturnType() { result.appliesTo(this) }
override string getAPrimaryQlClass() { result = "DelegateType" }
}
/**
@@ -794,6 +804,8 @@ class NullableType extends ValueType, DotNet::ConstructedGeneric, @nullable_type
override Location getALocation() { result = getUnderlyingType().getALocation() }
override Type getTypeArgument(int p) { p = 0 and result = getUnderlyingType() }
override string getAPrimaryQlClass() { result = "NullableType" }
}
/**
@@ -875,6 +887,8 @@ class PointerType extends DotNet::PointerType, Type, @pointer_type {
override Location getALocation() { result = getReferentType().getALocation() }
override string toString() { result = DotNet::PointerType.super.toString() }
override string getAPrimaryQlClass() { result = "PointerType" }
}
/**
@@ -882,6 +896,8 @@ class PointerType extends DotNet::PointerType, Type, @pointer_type {
*/
class DynamicType extends RefType, @dynamic_type {
override string toStringWithTypes() { result = "dynamic" }
override string getAPrimaryQlClass() { result = "DynamicType" }
}
/**
@@ -889,6 +905,8 @@ class DynamicType extends RefType, @dynamic_type {
*/
class ArglistType extends Type, @arglist_type {
override string toStringWithTypes() { result = "__arglist" }
override string getAPrimaryQlClass() { result = "ArglistType" }
}
/**

View File

@@ -213,6 +213,10 @@ module Gvn {
)
}
predicate isFullyConstructed() {
this.getKind().getNumberOfTypeParameters() - 1 = this.length()
}
GvnType getArg(int i) {
exists(GvnType head, ConstructedGvnTypeList tail |
this = TConstructedGvnTypeCons(head, tail)
@@ -224,47 +228,72 @@ module Gvn {
)
}
private GenericType getConstructedGenericDeclaringTypeAt(int i) {
i = 0 and
result = this.getKind().getConstructedSourceDeclaration()
or
result = this.getConstructedGenericDeclaringTypeAt(i - 1).getGenericDeclaringType()
}
private predicate isDeclaringTypeAt(int i) {
exists(this.getConstructedGenericDeclaringTypeAt(i - 1))
}
/**
* Gets a textual representation of this constructed type, restricted
* to the prefix `t` of the underlying source declaration type.
*
* The `toString()` calculation needs to be split up into prefixes, in
* order to apply the type arguments correctly. For example, a source
* declaration type `A<>.B.C<,>` applied to types `int, string, bool`
* needs to be printed as `A<int>.B.C<string,bool>`.
* Gets the `j`th `toString()` part of the `i`th nested component of this
* constructed type, if any. The nested components are sorted in reverse
* order, while the individual parts are sorted in normal order.
*/
language[monotonicAggregates]
private string toStringConstructed(GenericType t) {
t = this.getKind().getConstructedSourceDeclaration().getGenericDeclaringType*() and
exists(int offset, int children, string name, string nameArgs |
offset = t.getNumberOfDeclaringArguments() and
children = t.getNumberOfArgumentsSelf() and
name = getNameNested(t) and
if children = 0
then nameArgs = name
else
exists(string offsetArgs |
offsetArgs =
concat(int i |
i in [offset .. offset + children - 1]
|
this.getArg(i).toString(), "," order by i
) and
nameArgs = name.prefix(name.length() - children - 1) + "<" + offsetArgs + ">"
private string toStringConstructedPart(int i, int j) {
this.isFullyConstructed() and
exists(GenericType t |
t = this.getConstructedGenericDeclaringTypeAt(i) and
exists(int offset, int children, string name |
offset = t.getNumberOfDeclaringArguments() and
children = t.getNumberOfArgumentsSelf() and
name = getNameNested(t) and
if children = 0
then
j = 0 and result = name
or
this.isDeclaringTypeAt(i) and j = 1 and result = "."
else (
j = 0 and result = name.prefix(name.length() - children - 1) + "<"
or
j in [1 .. 2 * children - 1] and
if j % 2 = 0
then result = ","
else result = this.getArg((j + 1) / 2 + offset - 1).toString()
or
j = 2 * children and
result = ">"
or
this.isDeclaringTypeAt(i) and
j = 2 * children + 1 and
result = "."
)
|
offset = 0 and result = nameArgs
or
result = this.toStringConstructed(t.getGenericDeclaringType()) + "." + nameArgs
)
)
}
language[monotonicAggregates]
string toString() {
this.isFullyConstructed() and
exists(CompoundTypeKind k | k = this.getKind() |
result = k.toStringBuiltin(this.getArg(0).toString())
or
result = this.toStringConstructed(k.getConstructedSourceDeclaration())
result =
strictconcat(int i, int j, int offset |
exists(GenericType t, int children |
t = this.getConstructedGenericDeclaringTypeAt(i) and
children = t.getNumberOfArgumentsSelf() and
(if this.isDeclaringTypeAt(i) then offset = 1 else offset = 0) and
if children = 0 then j in [0 .. offset] else j in [0 .. 2 * children + offset]
)
|
this.toStringConstructedPart(i, j) order by i desc, j
)
)
}
@@ -482,7 +511,7 @@ module Gvn {
newtype TGvnType =
TLeafGvnType(LeafType t) or
TTypeParameterGvnType() or
TConstructedGvnType(ConstructedGvnTypeList l)
TConstructedGvnType(ConstructedGvnTypeList l) { l.isFullyConstructed() }
cached
newtype TConstructedGvnTypeList =

View File

@@ -48,6 +48,8 @@ class UsingNamespaceDirective extends UsingDirective, @using_namespace_directive
Namespace getImportedNamespace() { using_namespace_directives(this, result) }
override string toString() { result = "using ...;" }
override string getAPrimaryQlClass() { result = "UsingNamespaceDirective" }
}
/**
@@ -61,4 +63,6 @@ class UsingStaticDirective extends UsingDirective, @using_static_directive {
ValueOrRefType getTarget() { using_static_directives(this, getTypeRef(result)) }
override string toString() { result = "using static ...;" }
override string getAPrimaryQlClass() { result = "UsingStaticDirective" }
}

View File

@@ -194,6 +194,8 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top
override string toString() { result = this.getName() }
override string getAPrimaryQlClass() { result = "Parameter" }
/**
* Gets the default value of this parameter, if any. For example, the
* default value of `numberOfTries` is `3` in
@@ -407,6 +409,8 @@ class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent
override Location getALocation() { field_location(this, result) }
override string toString() { result = Variable.super.toString() }
override string getAPrimaryQlClass() { result = "Field" }
}
/**

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -1066,7 +1066,7 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
private predicate localFlowEntry(Node node, Configuration config) {
predicate localFlowEntry(Node node, Configuration config) {
nodeCand2(node, config) and
(
config.isSource(node) or
@@ -1650,53 +1650,53 @@ private class AccessPathOption extends TAccessPathOption {
* Holds if `node` is reachable with access path `ap` from a source in
* the configuration `config`.
*
* The Boolean `fromArg` records whether the node is reached through an
* The call context `cc` records whether the node is reached through an
* argument in a call, and if so, `argAp` records the access path of that
* argument.
*/
private predicate flowFwd(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwd0(node, fromArg, argAp, apf, ap, config) and
flowFwd0(node, cc, argAp, apf, ap, config) and
flowCand(node, _, _, apf, config)
}
private predicate flowFwd0(
Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowCand(node, _, _, _, config) and
config.isSource(node) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
(
exists(Node mid |
flowFwd(mid, fromArg, argAp, apf, ap, config) and
localFlowBigStep(mid, node, true, _, config, _)
exists(Node mid, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, apf, ap, localCC, config) and
localFlowBigStep(mid, node, true, _, config, localCC)
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, fromArg, argAp, _, nil, config) and
localFlowBigStep(mid, node, false, apf, config, _) and
exists(Node mid, AccessPathNil nil, LocalCallContext localCC |
flowFwdLocalEntry(mid, cc, argAp, _, nil, localCC, config) and
localFlowBigStep(mid, node, false, apf, config, localCC) and
apf = ap.(AccessPathNil).getFront()
)
or
exists(Node mid |
flowFwd(mid, _, _, apf, ap, config) and
jumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone()
)
or
exists(Node mid, AccessPathNil nil |
flowFwd(mid, _, _, _, nil, config) and
additionalJumpStep(mid, node, config) and
fromArg = false and
cc instanceof CallContextAny and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
apf = ap.(AccessPathNil).getFront()
@@ -1704,40 +1704,51 @@ private predicate flowFwd0(
)
or
// store
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, fromArg, argAp, config))
exists(TypedContent tc | flowFwdStore(node, tc, pop(tc, ap), apf, cc, argAp, config))
or
// read
exists(TypedContent tc |
flowFwdRead(node, _, push(tc, ap), apf, fromArg, argAp, config) and
flowFwdRead(node, _, push(tc, ap), apf, cc, argAp, config) and
flowFwdConsCand(tc, apf, ap, config)
)
or
// flow into a callable
flowFwdIn(_, node, _, _, apf, ap, config) and
fromArg = true and
flowFwdIn(_, node, _, cc, _, apf, ap, config) and
if flowCand(node, true, _, apf, config)
then argAp = TAccessPathSome(ap)
else argAp = TAccessPathNone()
or
// flow out of a callable
exists(DataFlowCall call |
flowFwdOut(call, node, fromArg, argAp, apf, ap, config) and
fromArg = false
exists(DataFlowCallable c |
flowFwdOut(call, node, any(CallContextNoCall innercc), c, argAp, apf, ap, config) and
if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
)
or
exists(AccessPath argAp0 |
flowFwdOutFromArg(call, node, argAp0, apf, ap, config) and
flowFwdIsEntered(call, fromArg, argAp, argAp0, config)
flowFwdIsEntered(call, cc, argAp, argAp0, config)
)
)
}
pragma[nomagic]
private predicate flowFwdLocalEntry(
Node node, CallContext cc, AccessPathOption argAp, AccessPathFront apf, AccessPath ap,
LocalCallContext localCC, Configuration config
) {
flowFwd(node, cc, argAp, apf, ap, config) and
localFlowEntry(node, config) and
localCC = getLocalCallContext(cc, node.getEnclosingCallable())
}
pragma[nomagic]
private predicate flowFwdStore(
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, TypedContent tc, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, AccessPathFront apf0 |
flowFwd(mid, fromArg, argAp, apf0, ap0, config) and
flowFwd(mid, cc, argAp, apf0, ap0, config) and
flowFwdStore0(mid, tc, node, apf0, apf, config)
)
}
@@ -1764,20 +1775,20 @@ private predicate flowFwdStore0(
pragma[nomagic]
private predicate flowFwdRead0(
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2,
boolean fromArg, AccessPathOption argAp, Configuration config
Node node1, TypedContent tc, AccessPathFrontHead apf0, AccessPath ap0, Node node2, CallContext cc,
AccessPathOption argAp, Configuration config
) {
flowFwd(node1, fromArg, argAp, apf0, ap0, config) and
flowFwd(node1, cc, argAp, apf0, ap0, config) and
readCandFwd(node1, tc, apf0, node2, config)
}
pragma[nomagic]
private predicate flowFwdRead(
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, boolean fromArg,
Node node, AccessPathFrontHead apf0, AccessPath ap0, AccessPathFront apf, CallContext cc,
AccessPathOption argAp, Configuration config
) {
exists(Node mid, TypedContent tc |
flowFwdRead0(mid, tc, apf0, ap0, node, fromArg, argAp, config) and
flowFwdRead0(mid, tc, apf0, ap0, node, cc, argAp, config) and
flowCand(node, _, _, apf, unbind(config)) and
flowCandConsCand(tc, apf, unbind(config))
)
@@ -1795,13 +1806,16 @@ private predicate flowFwdConsCand(
pragma[nomagic]
private predicate flowFwdIn(
DataFlowCall call, ParameterNode p, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, ParameterNode p, CallContext outercc, CallContext innercc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ArgumentNode arg, boolean allowsFieldFlow |
flowFwd(arg, fromArg, argAp, apf, ap, config) and
exists(ArgumentNode arg, boolean allowsFieldFlow, DataFlowCallable c |
flowFwd(arg, outercc, argAp, apf, ap, config) and
flowIntoCallNodeCand2(call, arg, p, allowsFieldFlow, config) and
flowCand(p, _, _, _, unbind(config))
c = p.getEnclosingCallable() and
c = resolveCall(call, outercc) and
flowCand(p, _, _, _, unbind(config)) and
if recordDataFlowCallSite(call, c) then innercc = TSpecificCall(call) else innercc = TSomeCall()
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1809,13 +1823,19 @@ private predicate flowFwdIn(
pragma[nomagic]
private predicate flowFwdOut(
DataFlowCall call, Node node, boolean fromArg, AccessPathOption argAp, AccessPathFront apf,
AccessPath ap, Configuration config
DataFlowCall call, Node node, CallContext innercc, DataFlowCallable innerc,
AccessPathOption argAp, AccessPathFront apf, AccessPath ap, Configuration config
) {
exists(ReturnNodeExt ret, boolean allowsFieldFlow |
flowFwd(ret, fromArg, argAp, apf, ap, config) and
flowFwd(ret, innercc, argAp, apf, ap, config) and
flowOutOfCallNodeCand2(call, ret, node, allowsFieldFlow, config) and
flowCand(node, _, _, _, unbind(config))
innerc = ret.getEnclosingCallable() and
flowCand(node, _, _, _, unbind(config)) and
(
resolveReturn(innercc, innerc, call)
or
innercc.(CallContextCall).matchesCall(call)
)
|
ap instanceof AccessPathNil or allowsFieldFlow = true
)
@@ -1826,7 +1846,7 @@ private predicate flowFwdOutFromArg(
DataFlowCall call, Node node, AccessPath argAp, AccessPathFront apf, AccessPath ap,
Configuration config
) {
flowFwdOut(call, node, true, TAccessPathSome(argAp), apf, ap, config)
flowFwdOut(call, node, any(CallContextCall ccc), _, TAccessPathSome(argAp), apf, ap, config)
}
/**
@@ -1834,10 +1854,10 @@ private predicate flowFwdOutFromArg(
*/
pragma[nomagic]
private predicate flowFwdIsEntered(
DataFlowCall call, boolean fromArg, AccessPathOption argAp, AccessPath ap, Configuration config
DataFlowCall call, CallContext cc, AccessPathOption argAp, AccessPath ap, Configuration config
) {
exists(ParameterNode p, AccessPathFront apf |
flowFwdIn(call, p, fromArg, argAp, apf, ap, config) and
flowFwdIn(call, p, cc, _, argAp, apf, ap, config) and
flowCand(p, true, TAccessPathFrontSome(_), apf, config)
)
}
@@ -1920,7 +1940,7 @@ private predicate flow0(
// flow out of a callable
flowOut(_, node, _, _, ap, config) and
toReturn = true and
if flowFwd(node, true, TAccessPathSome(_), _, ap, config)
if flowFwd(node, any(CallContextCall ccc), TAccessPathSome(_), _, ap, config)
then returnAp = TAccessPathSome(ap)
else returnAp = TAccessPathNone()
}
@@ -2006,9 +2026,10 @@ private predicate flowIsReturned(
DataFlowCall call, boolean toReturn, AccessPathOption returnAp, AccessPath ap,
Configuration config
) {
exists(ReturnNodeExt ret |
exists(ReturnNodeExt ret, CallContextCall ccc |
flowOut(call, ret, toReturn, returnAp, ap, config) and
flowFwd(ret, true, TAccessPathSome(_), _, ap, config)
flowFwd(ret, ccc, TAccessPathSome(_), _, ap, config) and
ccc.matchesCall(call)
)
}
@@ -2031,7 +2052,7 @@ private newtype TSummaryCtx =
exists(ReturnNodeExt ret, Configuration config, AccessPath ap0 |
parameterFlow(p, ap, ret.getEnclosingCallable(), config) and
flow(ret, true, TAccessPathSome(_), ap0, config) and
flowFwd(ret, true, TAccessPathSome(ap), _, ap0, config)
flowFwd(ret, any(CallContextCall ccc), TAccessPathSome(ap), _, ap0, config)
)
}
@@ -2352,7 +2373,7 @@ private predicate pathOutOfCallable0(
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}
@@ -2867,7 +2888,7 @@ private module FlowExploration {
) {
pos = getReturnPosition(mid.getNode()) and
innercc = mid.getCallContext() and
not innercc instanceof CallContextCall and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
config = mid.getConfiguration()
}

View File

@@ -512,13 +512,19 @@ abstract class CallContext extends TCallContext {
abstract predicate relevantFor(DataFlowCallable callable);
}
class CallContextAny extends CallContext, TAnyCallContext {
abstract class CallContextNoCall extends CallContext { }
class CallContextAny extends CallContextNoCall, TAnyCallContext {
override string toString() { result = "CcAny" }
override predicate relevantFor(DataFlowCallable callable) { any() }
}
abstract class CallContextCall extends CallContext { }
abstract class CallContextCall extends CallContext {
/** Holds if this call context may be `call`. */
bindingset[call]
abstract predicate matchesCall(DataFlowCall call);
}
class CallContextSpecificCall extends CallContextCall, TSpecificCall {
override string toString() {
@@ -529,6 +535,8 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
recordDataFlowCallSite(getCall(), callable)
}
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
DataFlowCall getCall() { this = TSpecificCall(result) }
}
@@ -538,9 +546,11 @@ class CallContextSomeCall extends CallContextCall, TSomeCall {
override predicate relevantFor(DataFlowCallable callable) {
exists(ParameterNode p | p.getEnclosingCallable() = callable)
}
override predicate matchesCall(DataFlowCall call) { any() }
}
class CallContextReturn extends CallContext, TReturn {
class CallContextReturn extends CallContextNoCall, TReturn {
override string toString() {
exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")")
}

View File

@@ -2354,7 +2354,7 @@ private predicate viableConstantBooleanParamArg(
)
}
int accessPathLimit() { result = 3 }
int accessPathLimit() { result = 5 }
/**
* Holds if `n` does not require a `PostUpdateNode` as it either cannot be

View File

@@ -78,6 +78,8 @@ class ThisAccess extends Access, @this_access_expr {
override Class getTarget() { result = this.getEnclosingCallable().getDeclaringType() }
override string toString() { result = "this access" }
override string getAPrimaryQlClass() { result = "ThisAccess" }
}
/**
@@ -96,6 +98,8 @@ class BaseAccess extends Access, @base_access_expr {
}
override string toString() { result = "base access" }
override string getAPrimaryQlClass() { result = "BaseAccess" }
}
/**
@@ -221,6 +225,8 @@ class ParameterAccess extends LocalScopeVariableAccess, @parameter_access_expr {
override Parameter getTarget() { expr_access(this, result) }
override string toString() { result = "access to parameter " + this.getTarget().getName() }
override string getAPrimaryQlClass() { result = "ParameterAccess" }
}
/**
@@ -273,6 +279,8 @@ class LocalVariableAccess extends LocalScopeVariableAccess, @local_variable_acce
not this instanceof LocalVariableDeclExpr and
result = "access to local variable " + this.getTarget().getName()
}
override string getAPrimaryQlClass() { result = "LocalVariableAccess" }
}
/**
@@ -325,6 +333,8 @@ class FieldAccess extends AssignableMemberAccess, VariableAccess, @field_access_
override Field getTarget() { expr_access(this, result) }
override string toString() { result = "access to field " + this.getTarget().getName() }
override string getAPrimaryQlClass() { result = "FieldAccess" }
}
/**
@@ -378,6 +388,8 @@ class MemberConstantAccess extends FieldAccess {
override MemberConstant getTarget() { expr_access(this, result) }
override string toString() { result = "access to constant " + this.getTarget().getName() }
override string getAPrimaryQlClass() { result = "MemberConstantAccess" }
}
/**
@@ -636,6 +648,8 @@ library class EventAccessExpr extends Expr, @event_access_expr {
*/
class EventAccess extends AssignableMemberAccess, EventAccessExpr {
override Event getTarget() { result = getEvent() }
override string getAPrimaryQlClass() { result = "EventAccess" }
}
/**
@@ -727,6 +741,8 @@ class MethodAccess extends MemberAccess, CallableAccess {
override Method getTarget() { expr_access(this, result) }
override string toString() { result = "access to method " + this.getTarget().getName() }
override string getAPrimaryQlClass() { result = "MethodAccess" }
}
/**
@@ -750,6 +766,8 @@ class LocalFunctionAccess extends CallableAccess {
override LocalFunction getTarget() { expr_access(this, result) }
override string toString() { result = "access to local function " + this.getTarget().getName() }
override string getAPrimaryQlClass() { result = "LocalFunctionAccess" }
}
/**
@@ -787,6 +805,8 @@ class TypeAccess extends MemberAccess, @type_access_expr {
override Type getTarget() { result = this.getType() }
override string toString() { result = "access to type " + this.getTarget().getName() }
override string getAPrimaryQlClass() { result = "TypeAccess" }
}
/**
@@ -807,6 +827,8 @@ class ArrayAccess extends ElementAccess, @array_access_expr {
// Although an array (element) can be assigned a value, there is no
// corresponding assignable (`ArrayAccess` does not extend `MemberAccess`)
override Assignable getTarget() { none() }
override string getAPrimaryQlClass() { result = "ArrayAccess" }
}
/**
@@ -840,4 +862,6 @@ class NamespaceAccess extends Access, @namespace_access_expr {
override Namespace getTarget() { expr_access(this, result) }
override string toString() { result = "access to namespace " + this.getTarget().getName() }
override string getAPrimaryQlClass() { result = "NamespaceAccess" }
}

View File

@@ -27,6 +27,8 @@ class UnaryArithmeticOperation extends ArithmeticOperation, UnaryOperation, @un_
*/
class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
override string getOperator() { result = "-" }
override string getAPrimaryQlClass() { result = "UnaryMinusExpr" }
}
/**
@@ -34,6 +36,8 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, @minus_expr {
*/
class UnaryPlusExpr extends UnaryArithmeticOperation, @plus_expr {
override string getOperator() { result = "+" }
override string getAPrimaryQlClass() { result = "UnaryPlusExpr" }
}
/**
@@ -61,18 +65,24 @@ class DecrementOperation extends MutatorOperation, @decr_op_expr {
/**
* A prefix increment operation, for example `++x`.
*/
class PreIncrExpr extends IncrementOperation, @pre_incr_expr { }
class PreIncrExpr extends IncrementOperation, @pre_incr_expr {
override string getAPrimaryQlClass() { result = "PreIncrExpr" }
}
/**
* A prefix decrement operation, for example `--x`.
*/
class PreDecrExpr extends DecrementOperation, @pre_decr_expr { }
class PreDecrExpr extends DecrementOperation, @pre_decr_expr {
override string getAPrimaryQlClass() { result = "PreDecrExpr" }
}
/**
* A postfix increment operation, for example `x++`.
*/
class PostIncrExpr extends IncrementOperation, @post_incr_expr {
override string toString() { result = "..." + this.getOperator() }
override string getAPrimaryQlClass() { result = "PostIncrExpr" }
}
/**
@@ -80,6 +90,8 @@ class PostIncrExpr extends IncrementOperation, @post_incr_expr {
*/
class PostDecrExpr extends DecrementOperation, @post_decr_expr {
override string toString() { result = "..." + this.getOperator() }
override string getAPrimaryQlClass() { result = "PostDecrExpr" }
}
/**
@@ -97,6 +109,8 @@ class BinaryArithmeticOperation extends ArithmeticOperation, BinaryOperation, @b
*/
class AddExpr extends BinaryArithmeticOperation, @add_expr {
override string getOperator() { result = "+" }
override string getAPrimaryQlClass() { result = "AddExpr" }
}
/**
@@ -104,6 +118,8 @@ class AddExpr extends BinaryArithmeticOperation, @add_expr {
*/
class SubExpr extends BinaryArithmeticOperation, @sub_expr {
override string getOperator() { result = "-" }
override string getAPrimaryQlClass() { result = "SubExpr" }
}
/**
@@ -111,6 +127,8 @@ class SubExpr extends BinaryArithmeticOperation, @sub_expr {
*/
class MulExpr extends BinaryArithmeticOperation, @mul_expr {
override string getOperator() { result = "*" }
override string getAPrimaryQlClass() { result = "MulExpr" }
}
/**
@@ -124,6 +142,8 @@ class DivExpr extends BinaryArithmeticOperation, @div_expr {
/** Gets the denominator of this division operation. */
Expr getDenominator() { result = getRightOperand() }
override string getAPrimaryQlClass() { result = "DivExpr" }
}
/**
@@ -131,4 +151,6 @@ class DivExpr extends BinaryArithmeticOperation, @div_expr {
*/
class RemExpr extends BinaryArithmeticOperation, @rem_expr {
override string getOperator() { result = "%" }
override string getAPrimaryQlClass() { result = "RemExpr" }
}

View File

@@ -43,6 +43,8 @@ class LocalVariableDeclAndInitExpr extends LocalVariableDeclExpr, Assignment {
override LocalVariableAccess getLValue() { result = Assignment.super.getLValue() }
override string toString() { result = LocalVariableDeclExpr.super.toString() + " = ..." }
override string getAPrimaryQlClass() { result = "LocalVariableDeclAndInitExpr" }
}
/**
@@ -52,6 +54,8 @@ class AssignExpr extends Assignment, @simple_assign_expr {
override string getOperator() { result = "=" }
override string toString() { result = "... = ..." }
override string getAPrimaryQlClass() { result = "AssignExpr" }
}
/**
@@ -101,6 +105,8 @@ class AssignArithmeticOperation extends AssignOperation, @assign_arith_expr { }
*/
class AssignAddExpr extends AssignArithmeticOperation, @assign_add_expr {
override string getOperator() { result = "+=" }
override string getAPrimaryQlClass() { result = "AssignAddExpr" }
}
/**
@@ -108,6 +114,8 @@ class AssignAddExpr extends AssignArithmeticOperation, @assign_add_expr {
*/
class AssignSubExpr extends AssignArithmeticOperation, @assign_sub_expr {
override string getOperator() { result = "-=" }
override string getAPrimaryQlClass() { result = "AssignSubExpr" }
}
/**
@@ -115,6 +123,8 @@ class AssignSubExpr extends AssignArithmeticOperation, @assign_sub_expr {
*/
class AssignMulExpr extends AssignArithmeticOperation, @assign_mul_expr {
override string getOperator() { result = "*=" }
override string getAPrimaryQlClass() { result = "AssignMulExpr" }
}
/**
@@ -122,6 +132,8 @@ class AssignMulExpr extends AssignArithmeticOperation, @assign_mul_expr {
*/
class AssignDivExpr extends AssignArithmeticOperation, @assign_div_expr {
override string getOperator() { result = "/=" }
override string getAPrimaryQlClass() { result = "AssignDivExpr" }
}
/**
@@ -129,6 +141,8 @@ class AssignDivExpr extends AssignArithmeticOperation, @assign_div_expr {
*/
class AssignRemExpr extends AssignArithmeticOperation, @assign_rem_expr {
override string getOperator() { result = "%=" }
override string getAPrimaryQlClass() { result = "AssignRemExpr" }
}
/**
@@ -146,6 +160,8 @@ class AssignBitwiseOperation extends AssignOperation, @assign_bitwise_expr { }
*/
class AssignAndExpr extends AssignBitwiseOperation, @assign_and_expr {
override string getOperator() { result = "&=" }
override string getAPrimaryQlClass() { result = "AssignAndExpr" }
}
/**
@@ -153,6 +169,8 @@ class AssignAndExpr extends AssignBitwiseOperation, @assign_and_expr {
*/
class AssignOrExpr extends AssignBitwiseOperation, @assign_or_expr {
override string getOperator() { result = "|=" }
override string getAPrimaryQlClass() { result = "AssignOrExpr" }
}
/**
@@ -160,6 +178,8 @@ class AssignOrExpr extends AssignBitwiseOperation, @assign_or_expr {
*/
class AssignXorExpr extends AssignBitwiseOperation, @assign_xor_expr {
override string getOperator() { result = "^=" }
override string getAPrimaryQlClass() { result = "AssignXorExpr" }
}
/**
@@ -167,6 +187,8 @@ class AssignXorExpr extends AssignBitwiseOperation, @assign_xor_expr {
*/
class AssignLShiftExpr extends AssignBitwiseOperation, @assign_lshift_expr {
override string getOperator() { result = "<<=" }
override string getAPrimaryQlClass() { result = "AssignLShiftExpr" }
}
/**
@@ -174,6 +196,8 @@ class AssignLShiftExpr extends AssignBitwiseOperation, @assign_lshift_expr {
*/
class AssignRShiftExpr extends AssignBitwiseOperation, @assign_rshift_expr {
override string getOperator() { result = ">>=" }
override string getAPrimaryQlClass() { result = "AssignRShiftExpr" }
}
/**
@@ -208,6 +232,8 @@ class AddOrRemoveEventExpr extends AssignOperation, @assign_event_expr {
*/
class AddEventExpr extends AddOrRemoveEventExpr, @add_event_expr {
override string toString() { result = "... += ..." }
override string getAPrimaryQlClass() { result = "AddEventExpr" }
}
/**
@@ -229,6 +255,8 @@ class AddEventExpr extends AddOrRemoveEventExpr, @add_event_expr {
*/
class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
override string toString() { result = "... -= ..." }
override string getAPrimaryQlClass() { result = "RemoveEventExpr" }
}
/**
@@ -236,4 +264,6 @@ class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
*/
class AssignCoalesceExpr extends AssignOperation, @assign_coalesce_expr {
override string toString() { result = "... ??= ..." }
override string getAPrimaryQlClass() { result = "AssignCoalesceExpr" }
}

View File

@@ -23,6 +23,8 @@ class UnaryBitwiseOperation extends BitwiseOperation, UnaryOperation, @un_bit_op
*/
class ComplementExpr extends UnaryBitwiseOperation, @bit_not_expr {
override string getOperator() { result = "~" }
override string getAPrimaryQlClass() { result = "ComplementExpr" }
}
/**
@@ -40,6 +42,8 @@ class BinaryBitwiseOperation extends BitwiseOperation, BinaryOperation, @bin_bit
*/
class LShiftExpr extends BinaryBitwiseOperation, @lshift_expr {
override string getOperator() { result = "<<" }
override string getAPrimaryQlClass() { result = "LShiftExpr" }
}
/**
@@ -47,6 +51,8 @@ class LShiftExpr extends BinaryBitwiseOperation, @lshift_expr {
*/
class RShiftExpr extends BinaryBitwiseOperation, @rshift_expr {
override string getOperator() { result = ">>" }
override string getAPrimaryQlClass() { result = "RShiftExpr" }
}
/**
@@ -54,6 +60,8 @@ class RShiftExpr extends BinaryBitwiseOperation, @rshift_expr {
*/
class BitwiseAndExpr extends BinaryBitwiseOperation, @bit_and_expr {
override string getOperator() { result = "&" }
override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
}
/**
@@ -61,6 +69,8 @@ class BitwiseAndExpr extends BinaryBitwiseOperation, @bit_and_expr {
*/
class BitwiseOrExpr extends BinaryBitwiseOperation, @bit_or_expr {
override string getOperator() { result = "|" }
override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
}
/**
@@ -68,4 +78,6 @@ class BitwiseOrExpr extends BinaryBitwiseOperation, @bit_or_expr {
*/
class BitwiseXorExpr extends BinaryBitwiseOperation, @bit_xor_expr {
override string getOperator() { result = "^" }
override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }
}

View File

@@ -297,6 +297,8 @@ class MethodCall extends Call, QualifiableExpr, LateBindableExpr, @method_invoca
override string toString() { result = "call to method " + concat(this.getTarget().getName()) }
override string getAPrimaryQlClass() { result = "MethodCall" }
override Expr getRawArgument(int i) {
if exists(getQualifier())
then
@@ -405,6 +407,8 @@ class ConstructorInitializer extends Call, @constructor_init_expr {
override string toString() { result = "call to constructor " + this.getTarget().getName() }
override string getAPrimaryQlClass() { result = "ConstructorInitializer" }
private ValueOrRefType getTargetType() {
result = this.getTarget().getDeclaringType().getSourceDeclaration()
}
@@ -493,6 +497,8 @@ class OperatorCall extends Call, LateBindableExpr, @operator_invocation_expr {
override Operator getARuntimeTarget() { result = Call.super.getARuntimeTarget() }
override string toString() { result = "call to operator " + this.getTarget().getName() }
override string getAPrimaryQlClass() { result = "OperatorCall" }
}
/**
@@ -594,6 +600,8 @@ class DelegateCall extends Call, @delegate_invocation_expr {
Expr getDelegateExpr() { result = this.getChild(-1) }
override string toString() { result = "delegate call" }
override string getAPrimaryQlClass() { result = "DelegateCall" }
}
/**
@@ -638,6 +646,8 @@ class PropertyCall extends AccessorCall, PropertyAccessExpr {
}
override string toString() { result = PropertyAccessExpr.super.toString() }
override string getAPrimaryQlClass() { result = "PropertyCall" }
}
/**
@@ -673,6 +683,8 @@ class IndexerCall extends AccessorCall, IndexerAccessExpr {
}
override string toString() { result = IndexerAccessExpr.super.toString() }
override string getAPrimaryQlClass() { result = "IndexerCall" }
}
/**
@@ -717,6 +729,8 @@ class EventCall extends AccessorCall, EventAccessExpr {
}
override string toString() { result = EventAccessExpr.super.toString() }
override string getAPrimaryQlClass() { result = "EventCall" }
}
/**
@@ -736,4 +750,6 @@ class LocalFunctionCall extends Call, @local_function_invocation_expr {
override LocalFunction getTarget() { expr_call(this, result) }
override string toString() { result = "call to local function " + getTarget().getName() }
override string getAPrimaryQlClass() { result = "LocalFunctionCall" }
}

View File

@@ -23,6 +23,8 @@ class EqualityOperation extends ComparisonOperation, @equality_op_expr { }
*/
class EQExpr extends EqualityOperation, @eq_expr {
override string getOperator() { result = "==" }
override string getAPrimaryQlClass() { result = "EQExpr" }
}
/**
@@ -30,6 +32,8 @@ class EQExpr extends EqualityOperation, @eq_expr {
*/
class NEExpr extends EqualityOperation, @ne_expr {
override string getOperator() { result = "!=" }
override string getAPrimaryQlClass() { result = "NEExpr" }
}
/**
@@ -64,6 +68,8 @@ class GTExpr extends RelationalOperation, @gt_expr {
override Expr getGreaterOperand() { result = getLeftOperand() }
override Expr getLesserOperand() { result = getRightOperand() }
override string getAPrimaryQlClass() { result = "GTExpr" }
}
/**
@@ -75,6 +81,8 @@ class LTExpr extends RelationalOperation, @lt_expr {
override Expr getGreaterOperand() { result = getRightOperand() }
override Expr getLesserOperand() { result = getLeftOperand() }
override string getAPrimaryQlClass() { result = "LTExpr" }
}
/**
@@ -86,6 +94,8 @@ class GEExpr extends RelationalOperation, @ge_expr {
override Expr getGreaterOperand() { result = getLeftOperand() }
override Expr getLesserOperand() { result = getRightOperand() }
override string getAPrimaryQlClass() { result = "GEExpr" }
}
/**
@@ -97,4 +107,6 @@ class LEExpr extends RelationalOperation, @le_expr {
override Expr getGreaterOperand() { result = getRightOperand() }
override Expr getLesserOperand() { result = getLeftOperand() }
override string getAPrimaryQlClass() { result = "LEExpr" }
}

View File

@@ -73,6 +73,8 @@ class ObjectInitializer extends ObjectOrCollectionInitializer, @object_init_expr
/** Holds if this object initializer has no member initializers. */
predicate hasNoMemberInitializers() { not exists(this.getAMemberInitializer()) }
override string getAPrimaryQlClass() { result = "ObjectInitializer" }
}
/**
@@ -94,6 +96,8 @@ class MemberInitializer extends AssignExpr {
/** Gets the initialized member. */
Member getInitializedMember() { result.getAnAccess() = this.getLValue() }
override string getAPrimaryQlClass() { result = "MemberInitializer" }
}
/**
@@ -142,6 +146,8 @@ class CollectionInitializer extends ObjectOrCollectionInitializer, @collection_i
/** Holds if this collection initializer has no element initializers. */
predicate hasNoElementInitializers() { not exists(this.getAnElementInitializer()) }
override string getAPrimaryQlClass() { result = "CollectionInitializer" }
}
/**
@@ -157,6 +163,8 @@ class CollectionInitializer extends ObjectOrCollectionInitializer, @collection_i
*/
class ElementInitializer extends MethodCall {
ElementInitializer() { this.getParent() instanceof CollectionInitializer }
override string getAPrimaryQlClass() { result = "ElementInitializer" }
}
/**
@@ -204,6 +212,10 @@ class ObjectCreation extends Call, LateBindableExpr, @object_creation_expr {
then result = this.getArgument(i)
else result = this.getArgument(i - 1)
}
override string getAPrimaryQlClass() {
result = "ObjectCreation" and not this instanceof AnonymousObjectCreation
}
}
/**
@@ -221,6 +233,8 @@ class AnonymousObjectCreation extends ObjectCreation {
AnonymousObjectCreation() { this.getObjectType() instanceof AnonymousClass }
override ObjectInitializer getInitializer() { result = this.getChild(-1) }
override string getAPrimaryQlClass() { result = "AnonymousObjectCreation" }
}
/**
@@ -255,7 +269,9 @@ class DelegateCreation extends Expr, @delegate_creation_expr {
* }
* ```
*/
class ExplicitDelegateCreation extends DelegateCreation, @explicit_delegate_creation_expr { }
class ExplicitDelegateCreation extends DelegateCreation, @explicit_delegate_creation_expr {
override string getAPrimaryQlClass() { result = "ExplicitDelegateCreation" }
}
/**
* An implicit delegate creation, for example the access to `M` on line 6 in
@@ -270,7 +286,9 @@ class ExplicitDelegateCreation extends DelegateCreation, @explicit_delegate_crea
* }
* ```
*/
class ImplicitDelegateCreation extends DelegateCreation, @implicit_delegate_creation_expr { }
class ImplicitDelegateCreation extends DelegateCreation, @implicit_delegate_creation_expr {
override string getAPrimaryQlClass() { result = "ImplicitDelegateCreation" }
}
/**
* An array initializer, for example `{ {0, 1}, {2, 3}, {4, 5} }` in
@@ -322,6 +340,8 @@ class ArrayInitializer extends Expr, @array_init_expr {
predicate hasNoElements() { not exists(this.getAnElement()) }
override string toString() { result = "{ ..., ... }" }
override string getAPrimaryQlClass() { result = "ArrayInitializer" }
}
/**
@@ -370,6 +390,8 @@ class ArrayCreation extends Expr, @array_creation_expr {
predicate isImplicitlyTyped() { implicitly_typed_array_creation(this) }
override string toString() { result = "array creation of type " + this.getType().getName() }
override string getAPrimaryQlClass() { result = "ArrayCreation" }
}
/**
@@ -377,6 +399,8 @@ class ArrayCreation extends Expr, @array_creation_expr {
*/
class Stackalloc extends ArrayCreation {
Stackalloc() { stackalloc_array_creation(this) }
override string getAPrimaryQlClass() { result = "Stackalloc" }
}
/**
@@ -405,6 +429,8 @@ class AnonymousFunctionExpr extends Expr, Callable, @anonymous_function_expr {
*/
class LambdaExpr extends AnonymousFunctionExpr, @lambda_expr {
override string toString() { result = "(...) => ..." }
override string getAPrimaryQlClass() { result = "LambdaExpr" }
}
/**
@@ -413,4 +439,6 @@ class LambdaExpr extends AnonymousFunctionExpr, @lambda_expr {
*/
class AnonymousMethodExpr extends AnonymousFunctionExpr, @anonymous_method_expr {
override string toString() { result = "delegate(...) { ... }" }
override string getAPrimaryQlClass() { result = "AnonymousMethodExpr" }
}

View File

@@ -42,6 +42,8 @@ class DynamicObjectCreation extends DynamicExpr, ObjectCreation {
override string toString() {
result = "dynamic object creation of type " + this.getType().getName()
}
override string getAPrimaryQlClass() { result = "DynamicObjectCreation" }
}
/**
@@ -66,6 +68,8 @@ class DynamicObjectCreation extends DynamicExpr, ObjectCreation {
*/
class DynamicMethodCall extends DynamicExpr, MethodCall {
override string toString() { result = "dynamic call to method " + getLateBoundTargetName() }
override string getAPrimaryQlClass() { result = "DynamicMethodCall" }
}
/**
@@ -94,6 +98,8 @@ class DynamicMethodCall extends DynamicExpr, MethodCall {
*/
class DynamicOperatorCall extends DynamicExpr, OperatorCall {
override string toString() { result = "dynamic call to operator " + getLateBoundTargetName() }
override string getAPrimaryQlClass() { result = "DynamicOperatorCall" }
}
/**
@@ -185,6 +191,8 @@ class DynamicMemberAccess extends DynamicAccess, MemberAccess, AssignableAccess,
@dynamic_member_access_expr {
override string toString() { result = "dynamic access to member " + getLateBoundTargetName() }
override string getAPrimaryQlClass() { result = "DynamicMemberAccess" }
// The target is unknown when the qualifier is a `dynamic` expression
override DynamicMember getTarget() { none() }
}
@@ -338,6 +346,8 @@ class DynamicAccessorCall extends DynamicAccess {
*/
class DynamicElementAccess extends DynamicAccess, ElementAccess, @dynamic_element_access_expr {
override string toString() { result = "dynamic access to element" }
override string getAPrimaryQlClass() { result = "DynamicElementAccess" }
}
/**

View File

@@ -165,6 +165,11 @@ class LocalVariableDeclExpr extends Expr, @local_var_decl_expr {
* for example `M(out int x)`.
*/
predicate isOutArgument() { expr_argument(this, 2) }
override string getAPrimaryQlClass() {
result = "LocalVariableDeclExpr" and
not this instanceof LocalVariableDeclAndInitExpr
}
}
/**
@@ -246,6 +251,8 @@ class ParenthesizedExpr extends Expr, @par_expr {
Expr getExpr() { result = this.getChild(0) }
override string toString() { result = "(...)" }
override string getAPrimaryQlClass() { result = "ParenthesizedExpr" }
}
/**
@@ -256,6 +263,8 @@ class CheckedExpr extends Expr, @checked_expr {
Expr getExpr() { result = this.getChild(0) }
override string toString() { result = "checked (...)" }
override string getAPrimaryQlClass() { result = "CheckedExpr" }
}
/**
@@ -266,6 +275,8 @@ class UncheckedExpr extends Expr, @unchecked_expr {
Expr getExpr() { result = this.getChild(0) }
override string toString() { result = "unchecked (...)" }
override string getAPrimaryQlClass() { result = "UncheckedExpr" }
}
cached
@@ -319,11 +330,15 @@ class PatternExpr extends Expr {
}
/** A discard pattern, for example `_` in `x is (_, false)` */
class DiscardPatternExpr extends DiscardExpr, PatternExpr { }
class DiscardPatternExpr extends DiscardExpr, PatternExpr {
override string getAPrimaryQlClass() { result = "DiscardPatternExpr" }
}
/** A constant pattern, for example `false` in `x is (_, false)`. */
class ConstantPatternExpr extends PatternExpr {
ConstantPatternExpr() { this.hasValue() }
override string getAPrimaryQlClass() { result = "ConstantPatternExpr" }
}
/**
@@ -343,7 +358,9 @@ class TypePatternExpr extends PatternExpr {
}
/** A type access pattern, for example `string` in `x is string`. */
class TypeAccessPatternExpr extends TypePatternExpr, TypeAccess { }
class TypeAccessPatternExpr extends TypePatternExpr, TypeAccess {
override string getAPrimaryQlClass() { result = "TypeAccessPatternExpr" }
}
/** A pattern that may bind a variable, for example `string s` in `x is string s`. */
class BindingPatternExpr extends PatternExpr {
@@ -362,6 +379,8 @@ class BindingPatternExpr extends PatternExpr {
/** A variable declaration pattern, for example `string s` in `x is string s`. */
class VariablePatternExpr extends BindingPatternExpr, LocalVariableDeclExpr {
override LocalVariableDeclExpr getVariableDeclExpr() { result = this }
override string getAPrimaryQlClass() { result = "VariablePatternExpr" }
}
/**
@@ -371,6 +390,8 @@ class VariablePatternExpr extends BindingPatternExpr, LocalVariableDeclExpr {
class RecursivePatternExpr extends BindingPatternExpr, @recursive_pattern_expr {
override string toString() { result = "{ ... }" }
override string getAPrimaryQlClass() { result = "RecursivePatternExpr" }
/**
* Gets the position patterns of this recursive pattern, if any.
* For example, `(1, _)`.
@@ -398,6 +419,8 @@ class PropertyPatternExpr extends Expr, @property_pattern_expr {
/** Gets the `n`th pattern. */
PatternExpr getPattern(int n) { result = this.getChild(n) }
override string getAPrimaryQlClass() { result = "PropertyPatternExpr" }
}
/**
@@ -409,6 +432,8 @@ class LabeledPatternExpr extends PatternExpr {
/** Gets the label of this pattern. */
string getLabel() { exprorstmt_name(this, result) }
override string getAPrimaryQlClass() { result = "LabeledPatternExpr" }
}
/** A positional pattern. For example, `(int x, int y)`. */
@@ -417,6 +442,8 @@ class PositionalPatternExpr extends Expr, @positional_pattern_expr {
/** Gets the `n`th pattern. */
PatternExpr getPattern(int n) { result = this.getChild(n) }
override string getAPrimaryQlClass() { result = "PositionalPatternExpr" }
}
/**
@@ -439,6 +466,8 @@ class IsExpr extends Expr, PatternMatch, @is_expr {
override PatternExpr getPattern() { result = this.getChild(1) }
override string toString() { result = "... is ..." }
override string getAPrimaryQlClass() { result = "IsExpr" }
}
/** A `switch` expression or statement. */
@@ -473,6 +502,8 @@ class SwitchExpr extends Expr, Switch, @switch_expr {
override SwitchCaseExpr getCase(int n) { result = this.getChild(n) }
override SwitchCaseExpr getACase() { result = this.getCase(_) }
override string getAPrimaryQlClass() { result = "SwitchExpr" }
}
/** A `case` expression or statement. */
@@ -510,6 +541,8 @@ class SwitchCaseExpr extends Expr, Case, @switch_case_expr {
// should match all cases due to the type of the expression.
this.getPattern() instanceof DiscardPatternExpr
}
override string getAPrimaryQlClass() { result = "SwitchCaseExpr" }
}
/**
@@ -574,6 +607,8 @@ class ExplicitCast extends Cast {
*/
class AsExpr extends Cast, @as_expr {
override string toString() { result = "... as ..." }
override string getAPrimaryQlClass() { result = "AsExpr" }
}
/**
@@ -581,6 +616,8 @@ class AsExpr extends Cast, @as_expr {
*/
class CastExpr extends Cast, @cast_expr {
override string toString() { result = "(...) ..." }
override string getAPrimaryQlClass() { result = "CastExpr" }
}
/**
@@ -594,6 +631,8 @@ class TypeofExpr extends Expr, @typeof_expr {
TypeAccess getTypeAccess() { result = this.getChild(0) }
override string toString() { result = "typeof(...)" }
override string getAPrimaryQlClass() { result = "TypeofExpr" }
}
/**
@@ -609,6 +648,8 @@ class DefaultValueExpr extends Expr, @default_expr {
override string toString() {
if exists(getTypeAccess()) then result = "default(...)" else result = "default"
}
override string getAPrimaryQlClass() { result = "DefaultValueExpr" }
}
/**
@@ -624,6 +665,8 @@ class SizeofExpr extends UnaryOperation, @sizeof_expr {
override string getOperator() { result = "sizeof(..)" }
override string toString() { result = "sizeof(..)" }
override string getAPrimaryQlClass() { result = "SizeofExpr" }
}
/**
@@ -662,6 +705,8 @@ class SizeofExpr extends UnaryOperation, @sizeof_expr {
*/
class PointerIndirectionExpr extends UnaryOperation, @pointer_indirection_expr {
override string getOperator() { result = "*" }
override string getAPrimaryQlClass() { result = "PointerIndirectionExpr" }
}
/**
@@ -679,6 +724,8 @@ class PointerIndirectionExpr extends UnaryOperation, @pointer_indirection_expr {
*/
class AddressOfExpr extends UnaryOperation, @address_of_expr {
override string getOperator() { result = "&" }
override string getAPrimaryQlClass() { result = "AddressOfExpr" }
}
/**
@@ -689,6 +736,8 @@ class AwaitExpr extends Expr, @await_expr {
Expr getExpr() { result = getChild(0) }
override string toString() { result = "await ..." }
override string getAPrimaryQlClass() { result = "AwaitExpr" }
}
/**
@@ -710,6 +759,8 @@ class NameOfExpr extends Expr, @nameof_expr {
* `nameof(x.F)`.
*/
Access getAccess() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "NameOfExpr" }
}
/**
@@ -724,6 +775,8 @@ class NameOfExpr extends Expr, @nameof_expr {
class InterpolatedStringExpr extends Expr, @interpolated_string_expr {
override string toString() { result = "$\"...\"" }
override string getAPrimaryQlClass() { result = "InterpolatedStringExpr" }
/**
* Gets the insert at index `i` in this interpolated string, if any. For
* example, the insert at index `i = 1` is `name` in `$"Hello, {name}!"`.
@@ -787,6 +840,8 @@ class ThrowExpr extends Expr, ThrowElement, @throw_expr {
*/
// overriden for more precise qldoc
override Expr getExpr() { result = ThrowElement.super.getExpr() }
override string getAPrimaryQlClass() { result = "ThrowExpr" }
}
/**
@@ -884,6 +939,8 @@ class TupleExpr extends Expr, @tuple_expr {
/** Holds if this tuple is a read access. */
predicate isReadAccess() { not this = getAnAssignOrForeachChild() }
override string getAPrimaryQlClass() { result = "TupleExpr" }
}
/**
@@ -902,6 +959,8 @@ class RefExpr extends Expr, @ref_expr {
override string toString() { result = "ref ..." }
override Type getType() { result = getExpr().getType() }
override string getAPrimaryQlClass() { result = "RefExpr" }
}
/**
@@ -913,6 +972,8 @@ class RefExpr extends Expr, @ref_expr {
*/
class DiscardExpr extends Expr, @discard_expr {
override string toString() { result = "_" }
override string getAPrimaryQlClass() { result = "DiscardExpr" }
}
private class UnknownExpr extends Expr, @unknown_expr {
@@ -944,6 +1005,8 @@ class RangeExpr extends Expr, @range_expr {
/** Holds if this range expression has a right hand operand. */
predicate hasEnd() { exists(this.getEnd()) }
override string getAPrimaryQlClass() { result = "RangeExpr" }
}
/** An index expression, for example `^1` meaning "1 from the end". */
@@ -951,6 +1014,8 @@ class IndexExpr extends Expr, @index_expr {
Expr getExpr() { result.getParent() = this }
override string toString() { result = "^..." }
override string getAPrimaryQlClass() { result = "IndexExpr" }
}
/**
@@ -968,4 +1033,6 @@ class SuppressNullableWarningExpr extends Expr, @suppress_nullable_warning_expr
Expr getExpr() { result.getParent() = this }
override string toString() { result = "...!" }
override string getAPrimaryQlClass() { result = "SuppressNullableWarningExpr" }
}

View File

@@ -27,12 +27,16 @@ class BoolLiteral extends Literal, @bool_literal_expr {
or
getValue() = "false" and result = false
}
override string getAPrimaryQlClass() { result = "BoolLiteral" }
}
/**
* A Unicode character literal, for example `'a'`.
*/
class CharLiteral extends Literal, @char_literal_expr { }
class CharLiteral extends Literal, @char_literal_expr {
override string getAPrimaryQlClass() { result = "CharLiteral" }
}
/**
* An integer literal. Either an `int` literal (`IntLiteral`), a `long`
@@ -44,22 +48,30 @@ class IntegerLiteral extends DotNet::IntLiteral, Literal, @integer_literal_expr
/**
* An `int` literal, for example `0`.
*/
class IntLiteral extends IntegerLiteral, @int_literal_expr { }
class IntLiteral extends IntegerLiteral, @int_literal_expr {
override string getAPrimaryQlClass() { result = "IntLiteral" }
}
/**
* A `long` literal, for example `-5L`.
*/
class LongLiteral extends IntegerLiteral, @long_literal_expr { }
class LongLiteral extends IntegerLiteral, @long_literal_expr {
override string getAPrimaryQlClass() { result = "LongLiteral" }
}
/**
* A `uint` literal, for example `5U`.
*/
class UIntLiteral extends IntegerLiteral, @uint_literal_expr { }
class UIntLiteral extends IntegerLiteral, @uint_literal_expr {
override string getAPrimaryQlClass() { result = "UIntLiteral" }
}
/**
* A `ulong` literal, for example `5UL`.
*/
class ULongLiteral extends IntegerLiteral, @ulong_literal_expr { }
class ULongLiteral extends IntegerLiteral, @ulong_literal_expr {
override string getAPrimaryQlClass() { result = "ULongLiteral" }
}
/**
* A floating point literal. Either a `float` literal (`FloatLiteral`), a
@@ -71,26 +83,36 @@ class RealLiteral extends Literal, @real_literal_expr { }
/**
* A `float` literal, for example `5F`.
*/
class FloatLiteral extends RealLiteral, @float_literal_expr { }
class FloatLiteral extends RealLiteral, @float_literal_expr {
override string getAPrimaryQlClass() { result = "FloatLiteral" }
}
/**
* A `double` literal, for example `5D`.
*/
class DoubleLiteral extends RealLiteral, @double_literal_expr { }
class DoubleLiteral extends RealLiteral, @double_literal_expr {
override string getAPrimaryQlClass() { result = "DoubleLiteral" }
}
/**
* A `decimal` literal, for example `5m`.
*/
class DecimalLiteral extends RealLiteral, @decimal_literal_expr { }
class DecimalLiteral extends RealLiteral, @decimal_literal_expr {
override string getAPrimaryQlClass() { result = "DecimalLiteral" }
}
/**
* A `string` literal, for example `"Hello, World!"`.
*/
class StringLiteral extends DotNet::StringLiteral, Literal, @string_literal_expr {
override string toString() { result = "\"" + getValue().replaceAll("\"", "\\\"") + "\"" }
override string getAPrimaryQlClass() { result = "StringLiteral" }
}
/**
* A `null` literal.
*/
class NullLiteral extends DotNet::NullLiteral, Literal, @null_literal_expr { }
class NullLiteral extends DotNet::NullLiteral, Literal, @null_literal_expr {
override string getAPrimaryQlClass() { result = "NullLiteral" }
}

View File

@@ -25,6 +25,8 @@ class UnaryLogicalOperation extends LogicalOperation, UnaryOperation, @un_log_op
*/
class LogicalNotExpr extends UnaryLogicalOperation, @log_not_expr {
override string getOperator() { result = "!" }
override string getAPrimaryQlClass() { result = "LogicalNotExpr" }
}
/**
@@ -41,6 +43,8 @@ class BinaryLogicalOperation extends LogicalOperation, BinaryOperation, @bin_log
*/
class LogicalAndExpr extends BinaryLogicalOperation, @log_and_expr {
override string getOperator() { result = "&&" }
override string getAPrimaryQlClass() { result = "LogicalAndExpr" }
}
/**
@@ -48,6 +52,8 @@ class LogicalAndExpr extends BinaryLogicalOperation, @log_and_expr {
*/
class LogicalOrExpr extends BinaryLogicalOperation, @log_or_expr {
override string getOperator() { result = "||" }
override string getAPrimaryQlClass() { result = "LogicalOrExpr" }
}
/**
@@ -61,6 +67,8 @@ class LogicalOrExpr extends BinaryLogicalOperation, @log_or_expr {
*/
class NullCoalescingExpr extends BinaryLogicalOperation, @null_coalescing_expr {
override string getOperator() { result = "??" }
override string getAPrimaryQlClass() { result = "NullCoalescingExpr" }
}
/**
@@ -92,4 +100,6 @@ class ConditionalExpr extends TernaryLogicalOperation, @conditional_expr {
override string getOperator() { result = "?" }
override string toString() { result = "... ? ... : ..." }
override string getAPrimaryQlClass() { result = "ConditionalExpr" }
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,211 @@
arguments.cs:
# 3| [Class] ArgumentsTest
# 5| 4: [InstanceConstructor] ArgumentsTest
#-----| 2: (Parameters)
# 5| 0: [Parameter] x
# 5| 1: [IntLiteral] 0
# 5| 1: [Parameter] y
# 5| 1: [IntLiteral] 0
# 6| 4: [BlockStmt] {...}
# 9| 5: [InstanceConstructor] ArgumentsTest
#-----| 2: (Parameters)
# 9| 0: [Parameter] x
# 9| 1: [Parameter] y
# 9| 2: [Parameter] z
# 10| 4: [BlockStmt] {...}
# 11| 0: [ExprStmt] ...;
# 11| 0: [AssignExpr] ... = ...
# 11| 0: [ParameterAccess] access to parameter x
# 11| 1: [ParameterAccess] access to parameter y
# 14| 6: [Method] f1
#-----| 2: (Parameters)
# 14| 0: [Parameter] x
# 14| 1: [IntLiteral] 1
# 14| 1: [Parameter] y
# 14| 1: [IntLiteral] 2
# 15| 4: [BlockStmt] {...}
# 18| 7: [Method] f2
#-----| 2: (Parameters)
# 18| 0: [Parameter] x
# 18| 1: [Parameter] y
# 18| 2: [Parameter] z
# 19| 4: [BlockStmt] {...}
# 20| 0: [ExprStmt] ...;
# 20| 0: [AssignExpr] ... = ...
# 20| 0: [ParameterAccess] access to parameter x
# 20| 1: [ParameterAccess] access to parameter y
# 23| 8: [Method] f
# 24| 4: [BlockStmt] {...}
# 25| 0: [LocalVariableDeclStmt] ... ...;
# 25| 0: [LocalVariableDeclAndInitExpr] Int32 x = ...
# 25| 0: [IntLiteral] 1
# 25| 1: [LocalVariableAccess] access to local variable x
# 27| 1: [ExprStmt] ...;
# 27| 0: [MethodCall] call to method f1
# 27| 0: [IntLiteral] 2
# 28| 2: [ExprStmt] ...;
# 28| 0: [MethodCall] call to method f2
# 28| 0: [LocalVariableAccess] access to local variable x
# 28| 1: [LocalVariableAccess] access to local variable x
# 28| 2: [LocalVariableAccess] access to local variable x
# 29| 3: [ExprStmt] ...;
# 29| 0: [ObjectCreation] object creation of type ArgumentsTest
# 29| 0: [LocalVariableAccess] access to local variable x
# 29| 1: [LocalVariableAccess] access to local variable x
# 29| 2: [LocalVariableAccess] access to local variable x
# 30| 4: [ExprStmt] ...;
# 30| 0: [ObjectCreation] object creation of type ArgumentsTest
# 30| 0: [IntLiteral] 10
# 30| 1: [IntLiteral] 5
# 33| 9: [Method] f3
#-----| 2: (Parameters)
# 33| 0: [Parameter] o
# 33| 1: [Parameter] args
# 34| 4: [BlockStmt] {...}
# 35| 0: [ExprStmt] ...;
# 35| 0: [MethodCall] call to method f3
# 35| 0: [IntLiteral] 0
# 35| 1: [IntLiteral] 1
# 35| 2: [IntLiteral] 2
# 36| 1: [ExprStmt] ...;
# 36| 0: [MethodCall] call to method f3
# 36| 0: [IntLiteral] 0
# 36| 1: [ArrayCreation] array creation of type Int32[]
# 36| -1: [ArrayInitializer] { ..., ... }
# 36| 0: [IntLiteral] 1
# 36| 1: [IntLiteral] 2
# 37| 2: [ExprStmt] ...;
# 37| 0: [MethodCall] call to method f3
# 37| 0: [IntLiteral] 1
# 37| 1: [IntLiteral] 0
# 38| 3: [ExprStmt] ...;
# 38| 0: [MethodCall] call to method f3
# 38| 0: [IntLiteral] 0
# 38| 1: [ParameterAccess] access to parameter args
# 39| 4: [ExprStmt] ...;
# 39| 0: [MethodCall] call to method f3
# 39| 0: [ParameterAccess] access to parameter args
# 39| 1: [IntLiteral] 0
# 40| 5: [ExprStmt] ...;
# 40| 0: [MethodCall] call to method f3
# 40| 0: [ArrayCreation] array creation of type Int32[]
# 40| -1: [ArrayInitializer] { ..., ... }
# 40| 0: [IntLiteral] 1
# 40| 1: [IntLiteral] 2
# 40| 1: [IntLiteral] 0
# 43| 10: [Method] f4
#-----| 2: (Parameters)
# 43| 0: [Parameter] args
# 44| 4: [BlockStmt] {...}
# 45| 0: [ExprStmt] ...;
# 45| 0: [MethodCall] call to method f4
# 45| 0: [ArrayCreation] array creation of type Object[]
# 45| -1: [ArrayInitializer] { ..., ... }
# 45| 0: [NullLiteral] null
# 45| 1: [NullLiteral] null
# 48| 11: [Property] Prop
# 48| 3: [Getter] get_Prop
# 48| 4: [Setter] set_Prop
#-----| 2: (Parameters)
# 48| 0: [Parameter] value
# 50| 12: [Indexer] Item
#-----| 1: (Parameters)
# 50| 0: [Parameter] a
# 50| 1: [Parameter] b
# 50| 3: [Getter] get_Item
#-----| 2: (Parameters)
# 50| 0: [Parameter] a
# 50| 1: [Parameter] b
# 50| 4: [AddExpr] ... + ...
# 50| 0: [ParameterAccess] access to parameter a
# 50| 1: [ParameterAccess] access to parameter b
# 50| 4: [Setter] set_Item
#-----| 2: (Parameters)
# 50| 0: [Parameter] a
# 50| 1: [Parameter] b
# 50| 2: [Parameter] value
# 50| 4: [BlockStmt] {...}
# 52| 13: [Method] f5
# 53| 4: [BlockStmt] {...}
# 54| 0: [ExprStmt] ...;
# 54| 0: [AssignExpr] ... = ...
# 54| 0: [IntLiteral] 0
# 54| 1: [PropertyCall] access to property Prop
# 55| 1: [ExprStmt] ...;
# 55| 0: [AssignExpr] ... = ...
# 55| 0: [IndexerCall] access to indexer
# 55| -1: [ThisAccess] this access
# 55| 0: [IntLiteral] 1
# 55| 1: [IntLiteral] 2
# 55| 1: [PropertyCall] access to property Prop
# 56| 2: [ExprStmt] ...;
# 56| 0: [AssignExpr] ... = ...
# 56| 0: [TupleExpr] (..., ...)
# 56| 0: [IntLiteral] 5
# 56| 1: [IntLiteral] 6
# 56| 1: [TupleExpr] (..., ...)
# 56| 0: [PropertyCall] access to property Prop
# 56| 1: [IndexerCall] access to indexer
# 56| -1: [ThisAccess] this access
# 56| 0: [IntLiteral] 3
# 56| 1: [IntLiteral] 4
# 57| 3: [ExprStmt] ...;
# 57| 0: [PostIncrExpr] ...++
# 57| 0: [PropertyCall] access to property Prop
# 58| 4: [ExprStmt] ...;
# 58| 0: [AssignAddExpr] ... += ...
# 58| 0: [IntLiteral] 7
# 58| 1: [PropertyCall] access to property Prop
# 59| 5: [ExprStmt] ...;
# 59| 0: [PostIncrExpr] ...++
# 59| 0: [IndexerCall] access to indexer
# 59| -1: [ThisAccess] this access
# 59| 0: [IntLiteral] 8
# 59| 1: [IntLiteral] 9
# 60| 6: [ExprStmt] ...;
# 60| 0: [AssignAddExpr] ... += ...
# 60| 0: [IntLiteral] 12
# 60| 1: [IndexerCall] access to indexer
# 60| -1: [ThisAccess] this access
# 60| 0: [IntLiteral] 10
# 60| 1: [IntLiteral] 11
# 61| 7: [LocalVariableDeclStmt] ... ...;
# 61| 0: [LocalVariableDeclAndInitExpr] (Int32,Int32) tuple = ...
# 61| 0: [TupleExpr] (..., ...)
# 61| 0: [IntLiteral] 13
# 61| 1: [IntLiteral] 14
# 61| 1: [LocalVariableAccess] access to local variable tuple
# 62| 8: [ExprStmt] ...;
# 62| 0: [AssignExpr] ... = ...
# 62| 0: [LocalVariableAccess] access to local variable tuple
# 62| 1: [TupleExpr] (..., ...)
# 62| 0: [PropertyCall] access to property Prop
# 62| 1: [IndexerCall] access to indexer
# 62| -1: [ThisAccess] this access
# 62| 0: [IntLiteral] 15
# 62| 1: [IntLiteral] 16
# 66| 14: [Method] f6
#-----| 0: (Attributes)
# 65| 1: [Attribute] [My(...)]
# 65| 0: [BoolLiteral] false
# 66| 4: [BlockStmt] {...}
# 69| 15: [Method] f7
#-----| 0: (Attributes)
# 68| 1: [Attribute] [My(...)]
# 68| 0: [BoolLiteral] true
# 68| 1: [StringLiteral] ""
# 68| 2: [IntLiteral] 0
# 69| 4: [BlockStmt] {...}
# 72| [Class] MyAttribute
#-----| 3: (Base types)
# 72| 0: [Class] Attribute
# 74| 4: [Field] x
# 75| 5: [IndexerProperty] y
# 75| 3: [Getter] get_y
# 75| 4: [Setter] set_y
#-----| 2: (Parameters)
# 75| 0: [Parameter] value
# 76| 6: [InstanceConstructor] MyAttribute
#-----| 2: (Parameters)
# 76| 0: [Parameter] b
# 76| 4: [BlockStmt] {...}

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,55 @@
Assignments.cs:
# 1| [Class] Assignments
# 3| 5: [Method] M
# 4| 4: [BlockStmt] {...}
# 5| 0: [LocalVariableDeclStmt] ... ...;
# 5| 0: [LocalVariableDeclAndInitExpr] Int32 x = ...
# 5| 0: [IntLiteral] 0
# 5| 1: [LocalVariableAccess] access to local variable x
# 6| 1: [ExprStmt] ...;
# 6| 0: [AssignAddExpr] ... += ...
# 6| 0: [IntLiteral] 1
# 6| 1: [LocalVariableAccess] access to local variable x
# 8| 2: [LocalVariableDeclStmt] ... ...;
# 8| 0: [LocalVariableDeclAndInitExpr] dynamic d = ...
# 8| 0: [CastExpr] (...) ...
# 8| 0: [IntLiteral] 0
# 8| 1: [LocalVariableAccess] access to local variable d
# 9| 3: [ExprStmt] ...;
# 9| 0: [AssignSubExpr] ... -= ...
# 9| 0: [IntLiteral] 2
# 9| 1: [LocalVariableAccess] access to local variable d
# 11| 4: [LocalVariableDeclStmt] ... ...;
# 11| 0: [LocalVariableDeclAndInitExpr] Assignments a = ...
# 11| 0: [ObjectCreation] object creation of type Assignments
# 11| 1: [LocalVariableAccess] access to local variable a
# 12| 5: [ExprStmt] ...;
# 12| 0: [AssignAddExpr] ... += ...
# 12| 0: [ThisAccess] this access
# 12| 1: [LocalVariableAccess] access to local variable a
# 14| 6: [ExprStmt] ...;
# 14| 0: [AddEventExpr] ... += ...
# 14| 0: [LambdaExpr] (...) => ...
#-----| 2: (Parameters)
# 14| 0: [Parameter] sender
# 14| 1: [Parameter] e
# 14| 4: [BlockStmt] {...}
# 14| 1: [EventAccess,EventCall] access to event Event
# 17| 6: [AddOperator] +
#-----| 2: (Parameters)
# 17| 0: [Parameter] x
# 17| 1: [Parameter] y
# 18| 4: [BlockStmt] {...}
# 19| 0: [ReturnStmt] return ...;
# 19| 0: [ParameterAccess] access to parameter x
# 22| 7: [DelegateType] EventHandler
#-----| 2: (Parameters)
# 22| 0: [Parameter] sender
# 22| 1: [Parameter] e
# 23| 8: [Event] Event
# 23| 3: [AddEventAccessor] add_Event
#-----| 2: (Parameters)
# 23| 0: [Parameter] value
# 23| 3: [RemoveEventAccessor] remove_Event
#-----| 2: (Parameters)
# 23| 0: [Parameter] value

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,73 @@
attributes.cs:
# 10| [Attribute] [AssemblyTitle(...)]
# 10| 0: [StringLiteral] "C# attributes test"
# 11| [Attribute] [AssemblyDescription(...)]
# 11| 0: [StringLiteral] "A test of C# attributes"
# 12| [Attribute] [AssemblyConfiguration(...)]
# 12| 0: [StringLiteral] ""
# 13| [Attribute] [AssemblyCompany(...)]
# 13| 0: [StringLiteral] "Semmle Plc"
# 14| [Attribute] [AssemblyProduct(...)]
# 14| 0: [StringLiteral] "Odasa"
# 15| [Attribute] [AssemblyCopyright(...)]
# 15| 0: [StringLiteral] "Copyright <20> Semmle 2018"
# 16| [Attribute] [AssemblyTrademark(...)]
# 16| 0: [StringLiteral] ""
# 17| [Attribute] [AssemblyCulture(...)]
# 17| 0: [StringLiteral] ""
# 22| [Attribute] [ComVisible(...)]
# 22| 0: [BoolLiteral] false
# 25| [Attribute] [Guid(...)]
# 25| 0: [StringLiteral] "2f70fdd6-14aa-4850-b053-d547adb1f476"
# 37| [Attribute] [AssemblyVersion(...)]
# 37| 0: [StringLiteral] "1.0.0.0"
# 38| [Attribute] [AssemblyFileVersion(...)]
# 38| 0: [StringLiteral] "1.0.0.0"
# 41| [Class] Foo
#-----| 0: (Attributes)
# 40| 1: [Attribute] [AttributeUsage(...)]
# 40| 0: [MemberConstantAccess] access to constant All
# 40| -1: [TypeAccess] access to type AttributeTargets
#-----| 3: (Base types)
# 41| 0: [Class] Attribute
# 44| 5: [Method] foo
#-----| 0: (Attributes)
# 43| 1: [Attribute] [Conditional(...)]
# 43| 0: [StringLiteral] "DEBUG2"
# 44| 4: [BlockStmt] {...}
# 47| [Class] Bar
# 49| 5: [Method] inc
#-----| 2: (Parameters)
# 49| 0: [Parameter] x
#-----| 0: (Attributes)
# 49| 1: [Attribute] [Foo(...)]
# 49| 4: [BlockStmt] {...}
# 49| 0: [ReturnStmt] return ...;
# 49| 0: [AddExpr] ... + ...
# 49| 0: [ParameterAccess] access to parameter x
# 49| 1: [IntLiteral] 1
# 52| 6: [Method] M1
#-----| 0: (Attributes)
# 51| 1: [Attribute] [My(...)]
# 51| 0: [BoolLiteral] false
# 52| 4: [BlockStmt] {...}
# 55| 7: [Method] M2
#-----| 0: (Attributes)
# 54| 1: [Attribute] [My(...)]
# 54| 0: [BoolLiteral] true
# 54| 1: [StringLiteral] ""
# 54| 2: [IntLiteral] 0
# 55| 4: [BlockStmt] {...}
# 58| [Class] MyAttribute
#-----| 3: (Base types)
# 58| 0: [Class] Attribute
# 60| 4: [Field] x
# 61| 5: [IndexerProperty] y
# 61| 3: [Getter] get_y
# 61| 4: [Setter] set_y
#-----| 2: (Parameters)
# 61| 0: [Parameter] value
# 62| 6: [InstanceConstructor] MyAttribute
#-----| 2: (Parameters)
# 62| 0: [Parameter] b
# 62| 4: [BlockStmt] {...}

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,17 @@
constructors.cs:
# 1| [NamespaceDeclaration] namespace ... { ... }
# 3| 1: [Class] Class
# 5| 4: [InstanceConstructor] Class
# 6| 4: [BlockStmt] {...}
# 8| 5: [InstanceConstructor] Class
#-----| 2: (Parameters)
# 8| 0: [Parameter] i
# 9| 4: [BlockStmt] {...}
# 11| 6: [StaticConstructor] Class
# 12| 4: [BlockStmt] {...}
# 14| 7: [Destructor] ~Class
# 15| 4: [BlockStmt] {...}
# 16| 0: [LocalVariableDeclStmt] ... ...;
# 16| 0: [LocalVariableDeclAndInitExpr] Int32 i = ...
# 16| 0: [IntLiteral] 0
# 16| 1: [LocalVariableAccess] access to local variable i

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,17 @@
Operator.cs:
# 3| [Class] C
# 5| 5: [ImplicitConversionOperator] implicit conversion
#-----| 2: (Parameters)
# 5| 0: [Parameter] i
# 5| 4: [BlockStmt] {...}
# 5| 0: [ReturnStmt] return ...;
# 5| 0: [NullLiteral] null
# 7| 6: [Field] x1
# 8| 7: [Field] x2
# 11| 8: [Method] M
# 12| 4: [BlockStmt] {...}
# 13| 0: [ExprStmt] ...;
# 13| 0: [AssignExpr] ... = ...
# 13| 0: [OperatorCall] call to operator implicit conversion
# 13| 0: [FieldAccess] access to field x1
# 13| 1: [FieldAccess] access to field x2

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,236 @@
csharp6.cs:
# 10| [Class] TestCSharp6
# 12| 6: [Property] Value
# 15| 2: [AssignExpr] ... = ...
# 15| 0: [IntLiteral] 20
# 12| 1: [PropertyCall] access to property Value
# 14| 3: [Getter] get_Value
# 17| 7: [Method] Fn
#-----| 2: (Parameters)
# 17| 0: [Parameter] x
# 17| 4: [MethodCall] call to method WriteLine
# 17| 0: [ParameterAccess] access to parameter x
# 19| 8: [Method] Main
# 20| 4: [BlockStmt] {...}
# 21| 0: [TryStmt] try {...} ...
# 22| 0: [BlockStmt] {...}
# 23| 0: [LocalVariableDeclStmt] ... ...;
# 23| 0: [LocalVariableDeclAndInitExpr] String foo = ...
# 23| 0: [NameOfExpr] nameof(...)
# 23| 0: [TypeAccess] access to type TestCSharp6
# 23| 1: [LocalVariableAccess] access to local variable foo
# 23| 1: [LocalVariableDeclAndInitExpr] String bar = ...
# 23| 0: [NullLiteral] null
# 23| 1: [LocalVariableAccess] access to local variable bar
# 25| 1: [ExprStmt] ...;
# 25| 0: [MethodCall] call to method WriteLine
# 25| 0: [InterpolatedStringExpr] $"..."
# 25| 0: [NameOfExpr] nameof(...)
# 25| 0: [LocalVariableAccess] access to local variable foo
# 25| 1: [StringLiteral] " is "
# 25| 2: [LocalVariableAccess] access to local variable foo
# 25| 3: [StringLiteral] ", and "
# 25| 4: [NameOfExpr] nameof(...)
# 25| 0: [LocalVariableAccess] access to local variable bar
# 25| 5: [StringLiteral] " has length "
# 25| 6: [NullCoalescingExpr] ... ?? ...
# 25| 0: [PropertyCall] access to property Length
# 25| -1: [LocalVariableAccess] access to local variable bar
# 25| 1: [IntLiteral] 0
# 27| 2: [ExprStmt] ...;
# 27| 0: [MethodCall] call to method Fn
# 27| 0: [InterpolatedStringExpr] $"..."
# 27| 0: [NameOfExpr] nameof(...)
# 27| 0: [LocalVariableAccess] access to local variable foo
# 27| 1: [StringLiteral] " is "
# 27| 2: [LocalVariableAccess] access to local variable foo
# 27| 3: [StringLiteral] ", and "
# 27| 4: [NameOfExpr] nameof(...)
# 27| 0: [LocalVariableAccess] access to local variable bar
# 27| 5: [StringLiteral] " has length "
# 27| 6: [NullCoalescingExpr] ... ?? ...
# 27| 0: [PropertyCall] access to property Length
# 27| -1: [LocalVariableAccess] access to local variable bar
# 27| 1: [IntLiteral] 0
# 29| 3: [LocalVariableDeclStmt] ... ...;
# 29| 0: [LocalVariableDeclAndInitExpr] Nullable<Boolean> anythingInBar = ...
# 29| 0: [MethodCall] call to method Any
# 29| -1: [LocalVariableAccess] access to local variable bar
# 29| 1: [LocalVariableAccess] access to local variable anythingInBar
# 30| 4: [LocalVariableDeclStmt] ... ...;
# 30| 0: [LocalVariableDeclAndInitExpr] Nullable<Int32> countTInFoo = ...
# 30| 0: [MethodCall] call to method Count
# 30| -1: [MethodCall] call to method Select
# 30| -1: [MethodCall] call to method ToUpper
# 30| -1: [LocalVariableAccess] access to local variable foo
# 30| 0: [LambdaExpr] (...) => ...
#-----| 2: (Parameters)
# 30| 0: [Parameter] c
# 30| 4: [EQExpr] ... == ...
# 30| 0: [CastExpr] (...) ...
# 30| 0: [ParameterAccess] access to parameter c
# 30| 1: [CastExpr] (...) ...
# 30| 0: [CharLiteral] T
# 30| 1: [LocalVariableAccess] access to local variable countTInFoo
# 32| 5: [LocalVariableDeclStmt] ... ...;
# 32| 0: [LocalVariableDeclAndInitExpr] Nullable<Char> testElementBinding = ...
# 32| 0: [IndexerCall] access to indexer
# 32| -1: [IndexerCall] access to indexer
# 32| -1: [ObjectCreation] object creation of type Dictionary<Int32,String>
# 32| 0: [IntLiteral] 2
# 32| 0: [IntLiteral] 1
# 32| 1: [LocalVariableAccess] access to local variable testElementBinding
# 34| 1: [SpecificCatchClause] catch (...) {...}
# 35| 1: [BlockStmt] {...}
# 34| 2: [EQExpr] ... == ...
# 34| 0: [PropertyCall] access to property Value
# 34| 1: [IntLiteral] 20
# 37| 2: [GeneralCatchClause] catch {...}
# 38| 1: [BlockStmt] {...}
# 37| 2: [EQExpr] ... == ...
# 37| 0: [PropertyCall] access to property Value
# 37| 1: [IntLiteral] 30
# 40| 3: [GeneralCatchClause] catch {...}
# 41| 1: [BlockStmt] {...}
# 45| 9: [EQOperator] ==
#-----| 2: (Parameters)
# 45| 0: [Parameter] t1
# 45| 1: [Parameter] t2
# 45| 4: [BoolLiteral] true
# 46| 10: [NEOperator] !=
#-----| 2: (Parameters)
# 46| 0: [Parameter] t1
# 46| 1: [Parameter] t2
# 46| 4: [BoolLiteral] false
# 48| 11: [Property] ExprProperty
# 48| 3: [Getter] get_ExprProperty
# 48| 4: [IntLiteral] 3
# 50| 12: [Indexer] Item
#-----| 1: (Parameters)
# 50| 0: [Parameter] i
# 50| 3: [Getter] get_Item
#-----| 2: (Parameters)
# 50| 0: [Parameter] i
# 50| 4: [ParameterAccess] access to parameter i
# 53| [Class] IndexInitializers
# 55| 5: [Class] Compound
# 57| 5: [Field] DictionaryField
# 58| 6: [IndexerProperty] DictionaryProperty
# 58| 3: [Getter] get_DictionaryProperty
# 58| 4: [Setter] set_DictionaryProperty
#-----| 2: (Parameters)
# 58| 0: [Parameter] value
# 59| 7: [Field] ArrayField
# 60| 8: [Property] ArrayProperty
# 60| 3: [Getter] get_ArrayProperty
# 60| 4: [Setter] set_ArrayProperty
#-----| 2: (Parameters)
# 60| 0: [Parameter] value
# 61| 9: [Field] ArrayField2
# 62| 10: [Property] ArrayProperty2
# 62| 3: [Getter] get_ArrayProperty2
# 62| 4: [Setter] set_ArrayProperty2
#-----| 2: (Parameters)
# 62| 0: [Parameter] value
# 65| 6: [Method] Test
# 66| 4: [BlockStmt] {...}
# 68| 0: [LocalVariableDeclStmt] ... ...;
# 68| 0: [LocalVariableDeclAndInitExpr] Dictionary<Int32,String> dict = ...
# 68| 0: [ObjectCreation] object creation of type Dictionary<Int32,String>
# 68| -1: [ObjectInitializer] { ..., ... }
# 68| 0: [MemberInitializer] ... = ...
# 68| 0: [StringLiteral] "Zero"
# 68| 1: [IndexerCall] access to indexer
# 68| 0: [IntLiteral] 0
# 68| 1: [MemberInitializer] ... = ...
# 68| 0: [StringLiteral] "One"
# 68| 1: [IndexerCall] access to indexer
# 68| 0: [IntLiteral] 1
# 68| 2: [MemberInitializer] ... = ...
# 68| 0: [StringLiteral] "Two"
# 68| 1: [IndexerCall] access to indexer
# 68| 0: [IntLiteral] 2
# 68| 1: [LocalVariableAccess] access to local variable dict
# 71| 1: [LocalVariableDeclStmt] ... ...;
# 71| 0: [LocalVariableDeclAndInitExpr] Compound compound = ...
# 71| 0: [ObjectCreation] object creation of type Compound
# 72| -1: [ObjectInitializer] { ..., ... }
# 73| 0: [MemberInitializer] ... = ...
# 73| 0: [ObjectInitializer] { ..., ... }
# 73| 0: [MemberInitializer] ... = ...
# 73| 0: [StringLiteral] "Zero"
# 73| 1: [IndexerCall] access to indexer
# 73| 0: [IntLiteral] 0
# 73| 1: [MemberInitializer] ... = ...
# 73| 0: [StringLiteral] "One"
# 73| 1: [IndexerCall] access to indexer
# 73| 0: [IntLiteral] 1
# 73| 2: [MemberInitializer] ... = ...
# 73| 0: [StringLiteral] "Two"
# 73| 1: [IndexerCall] access to indexer
# 73| 0: [IntLiteral] 2
# 73| 1: [FieldAccess] access to field DictionaryField
# 74| 1: [MemberInitializer] ... = ...
# 74| 0: [ObjectInitializer] { ..., ... }
# 74| 0: [MemberInitializer] ... = ...
# 74| 0: [StringLiteral] "Three"
# 74| 1: [IndexerCall] access to indexer
# 74| 0: [IntLiteral] 3
# 74| 1: [MemberInitializer] ... = ...
# 74| 0: [StringLiteral] "Two"
# 74| 1: [IndexerCall] access to indexer
# 74| 0: [IntLiteral] 2
# 74| 2: [MemberInitializer] ... = ...
# 74| 0: [StringLiteral] "One"
# 74| 1: [IndexerCall] access to indexer
# 74| 0: [IntLiteral] 1
# 74| 1: [PropertyCall] access to property DictionaryProperty
# 75| 2: [MemberInitializer] ... = ...
# 75| 0: [ObjectInitializer] { ..., ... }
# 75| 0: [MemberInitializer] ... = ...
# 75| 0: [StringLiteral] "Zero"
# 75| 1: [ArrayAccess] access to array element
# 75| 0: [IntLiteral] 0
# 75| 1: [MemberInitializer] ... = ...
# 75| 0: [StringLiteral] "One"
# 75| 1: [ArrayAccess] access to array element
# 75| 0: [IntLiteral] 1
# 75| 1: [FieldAccess] access to field ArrayField
# 76| 3: [MemberInitializer] ... = ...
# 76| 0: [ObjectInitializer] { ..., ... }
# 76| 0: [MemberInitializer] ... = ...
# 76| 0: [StringLiteral] "i"
# 76| 1: [ArrayAccess] access to array element
# 76| 0: [IntLiteral] 0
# 76| 1: [IntLiteral] 1
# 76| 1: [MemberInitializer] ... = ...
# 76| 0: [StringLiteral] "1"
# 76| 1: [ArrayAccess] access to array element
# 76| 0: [IntLiteral] 1
# 76| 1: [IntLiteral] 0
# 76| 1: [FieldAccess] access to field ArrayField2
# 77| 4: [MemberInitializer] ... = ...
# 77| 0: [ObjectInitializer] { ..., ... }
# 77| 0: [MemberInitializer] ... = ...
# 77| 0: [StringLiteral] "One"
# 77| 1: [ArrayAccess] access to array element
# 77| 0: [IntLiteral] 1
# 77| 1: [MemberInitializer] ... = ...
# 77| 0: [StringLiteral] "Two"
# 77| 1: [ArrayAccess] access to array element
# 77| 0: [IntLiteral] 2
# 77| 1: [PropertyCall] access to property ArrayProperty
# 78| 5: [MemberInitializer] ... = ...
# 78| 0: [ObjectInitializer] { ..., ... }
# 78| 0: [MemberInitializer] ... = ...
# 78| 0: [StringLiteral] "i"
# 78| 1: [ArrayAccess] access to array element
# 78| 0: [IntLiteral] 0
# 78| 1: [IntLiteral] 1
# 78| 1: [MemberInitializer] ... = ...
# 78| 0: [StringLiteral] "1"
# 78| 1: [ArrayAccess] access to array element
# 78| 0: [IntLiteral] 1
# 78| 1: [IntLiteral] 0
# 78| 1: [PropertyCall] access to property ArrayProperty2
# 71| 1: [LocalVariableAccess] access to local variable compound

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,67 @@
csharp71.cs:
# 3| [Class] DefaultLiterals
# 5| 5: [Method] f
# 6| 4: [BlockStmt] {...}
# 7| 0: [LocalVariableDeclStmt] ... ...;
# 7| 0: [LocalVariableDeclAndInitExpr] Int32 x = ...
# 7| 0: [CastExpr] (...) ...
# 7| 0: [DefaultValueExpr] default
# 7| 1: [LocalVariableAccess] access to local variable x
# 7| 1: [LocalVariableDeclAndInitExpr] Int32 y = ...
# 7| 0: [DefaultValueExpr] default(...)
# 7| 0: [TypeAccess] access to type Int32
# 7| 1: [LocalVariableAccess] access to local variable y
# 8| 1: [IfStmt] if (...) ...
# 8| 0: [EQExpr] ... == ...
# 8| 0: [LocalVariableAccess] access to local variable x
# 8| 1: [CastExpr] (...) ...
# 8| 0: [DefaultValueExpr] default
# 9| 1: [EmptyStmt] ;
# 10| 2: [SwitchStmt] switch (...) {...}
# 10| 0: [LocalVariableAccess] access to local variable x
# 12| 0: [CaseStmt] case ...:
# 12| 0: [DiscardPatternExpr] _
# 12| 1: [BreakStmt] break;
# 14| 3: [ExprStmt] ...;
# 14| 0: [AssignExpr] ... = ...
# 14| 0: [CastExpr] (...) ...
# 14| 0: [DefaultValueExpr] default
# 14| 1: [LocalVariableAccess] access to local variable x
# 15| 4: [LocalVariableDeclStmt] ... ...;
# 15| 0: [LocalVariableDeclAndInitExpr] String s = ...
# 15| 0: [CastExpr] (...) ...
# 15| 0: [DefaultValueExpr] default
# 15| 1: [LocalVariableAccess] access to local variable s
# 16| 5: [LocalVariableDeclStmt] ... ...;
# 16| 0: [LocalVariableDeclAndInitExpr] Boolean b = ...
# 16| 0: [CastExpr] (...) ...
# 16| 0: [DefaultValueExpr] default
# 16| 1: [LocalVariableAccess] access to local variable b
# 17| 6: [LocalVariableDeclStmt] ... ...;
# 17| 0: [LocalVariableDeclAndInitExpr] Double d = ...
# 17| 0: [CastExpr] (...) ...
# 17| 0: [DefaultValueExpr] default
# 17| 1: [LocalVariableAccess] access to local variable d
# 21| [Class] IsConstants
# 23| 5: [Method] f
# 24| 4: [BlockStmt] {...}
# 25| 0: [LocalVariableDeclStmt] ... ...;
# 25| 0: [LocalVariableDeclExpr] Boolean b
# 26| 1: [ExprStmt] ...;
# 26| 0: [AssignExpr] ... = ...
# 26| 0: [IsExpr] ... is ...
# 26| 0: [ObjectCreation] object creation of type Object
# 26| 1: [ConstantPatternExpr,StringLiteral] "abc"
# 26| 1: [LocalVariableAccess] access to local variable b
# 27| 2: [ExprStmt] ...;
# 27| 0: [AssignExpr] ... = ...
# 27| 0: [IsExpr] ... is ...
# 27| 0: [StringLiteral] ""
# 27| 1: [ConstantPatternExpr,NullLiteral] null
# 27| 1: [LocalVariableAccess] access to local variable b
# 28| 3: [ExprStmt] ...;
# 28| 0: [AssignExpr] ... = ...
# 28| 0: [IsExpr] ... is ...
# 28| 0: [LocalVariableAccess] access to local variable b
# 28| 1: [BoolLiteral,ConstantPatternExpr] true
# 28| 1: [LocalVariableAccess] access to local variable b

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,39 @@
csharp72.cs:
# 5| [Class] InModifiers
# 7| 5: [Struct] S
# 11| 6: [Method] F
#-----| 2: (Parameters)
# 11| 0: [Parameter] s
# 12| 4: [BlockStmt] {...}
# 15| 7: [Method] CallF
# 16| 4: [BlockStmt] {...}
# 17| 0: [LocalVariableDeclStmt] ... ...;
# 17| 0: [LocalVariableDeclAndInitExpr] S s = ...
# 17| 0: [ObjectCreation] object creation of type S
# 17| 1: [LocalVariableAccess] access to local variable s
# 18| 1: [ExprStmt] ...;
# 18| 0: [MethodCall] call to method F
# 18| 0: [LocalVariableAccess] access to local variable s
# 22| [Class] RefReadonlyReturns
# 24| 5: [Field] s
# 26| 6: [Method] F
# 27| 4: [BlockStmt] {...}
# 28| 0: [ReturnStmt] return ...;
# 28| 0: [RefExpr] ref ...
# 28| 0: [FieldAccess] access to field s
# 31| 7: [DelegateType] Del
# 46| [Class] NumericLiterals
# 48| 5: [Field] binaryValue
# 48| 1: [AssignExpr] ... = ...
# 48| 0: [IntLiteral] 85
# 48| 1: [FieldAccess] access to field binaryValue
# 51| [Class] PrivateProtected
# 53| 5: [Field] X
# 53| 1: [AssignExpr] ... = ...
# 53| 0: [IntLiteral] 1
# 53| 1: [FieldAccess] access to field X
# 55| 6: [Method] F
# 55| 4: [BlockStmt] {...}
# 34| [Struct] ReadonlyStruct
# 38| [Struct] RefStruct
# 42| [Struct] ReadonlyRefStruct

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,80 @@
csharp73.cs:
# 5| [Class] StackAllocs
# 7| 5: [Method] Fn
# 8| 4: [BlockStmt] {...}
# 9| 0: [LocalVariableDeclStmt] ... ...;
# 9| 0: [LocalVariableDeclAndInitExpr] Char* arr1 = ...
# 9| 0: [Stackalloc] array creation of type Char*
# 9| -1: [ArrayInitializer] { ..., ... }
# 9| 0: [CharLiteral] x
# 9| 1: [CharLiteral] y
# 9| 1: [LocalVariableAccess] access to local variable arr1
# 10| 1: [LocalVariableDeclStmt] ... ...;
# 10| 0: [LocalVariableDeclAndInitExpr] Char* arr2 = ...
# 10| 0: [Stackalloc] array creation of type Char*
# 10| -1: [ArrayInitializer] { ..., ... }
# 10| 0: [CharLiteral] x
# 10| 0: [IntLiteral] 1
# 10| 1: [LocalVariableAccess] access to local variable arr2
# 11| 2: [LocalVariableDeclStmt] ... ...;
# 11| 0: [LocalVariableDeclAndInitExpr] Char[] arr3 = ...
# 11| 0: [ArrayCreation] array creation of type Char[]
# 11| -1: [ArrayInitializer] { ..., ... }
# 11| 0: [CharLiteral] x
# 11| 1: [LocalVariableAccess] access to local variable arr3
# 12| 3: [LocalVariableDeclStmt] ... ...;
# 12| 0: [LocalVariableDeclAndInitExpr] Char* arr4 = ...
# 12| 0: [Stackalloc] array creation of type Char*
# 12| 0: [IntLiteral] 10
# 12| 1: [LocalVariableAccess] access to local variable arr4
# 13| 4: [LocalVariableDeclStmt] ... ...;
# 13| 0: [LocalVariableDeclAndInitExpr] Char[] arr5 = ...
# 13| 0: [ArrayCreation] array creation of type Char[]
# 13| 0: [IntLiteral] 10
# 13| 1: [LocalVariableAccess] access to local variable arr5
# 14| 5: [LocalVariableDeclStmt] ... ...;
# 14| 0: [LocalVariableDeclAndInitExpr] Int32* arr6 = ...
# 14| 0: [Stackalloc] array creation of type Int32*
# 14| -1: [ArrayInitializer] { ..., ... }
# 14| 0: [IntLiteral] 1
# 14| 1: [IntLiteral] 2
# 14| 2: [IntLiteral] 3
# 14| 1: [LocalVariableAccess] access to local variable arr6
# 18| [Class] PinnedReference
# 20| 5: [Method] F
# 21| 4: [BlockStmt] {...}
# 22| 0: [LocalVariableDeclStmt] ... ...;
# 22| 0: [LocalVariableDeclAndInitExpr] Span<Int32> t = ...
# 22| 0: [OperatorCall] call to operator implicit conversion
# 22| 0: [ArrayCreation] array creation of type Int32[]
# 22| 0: [IntLiteral] 10
# 22| 1: [LocalVariableAccess] access to local variable t
# 25| 1: [BlockStmt] {...}
# 42| [Class] ExpressionVariables
# 44| 4: [InstanceConstructor] ExpressionVariables
#-----| 2: (Parameters)
# 44| 0: [Parameter] x
# 45| 4: [BlockStmt] {...}
# 46| 0: [ExprStmt] ...;
# 46| 0: [AssignExpr] ... = ...
# 46| 0: [IntLiteral] 5
# 46| 1: [ParameterAccess] access to parameter x
# 49| 5: [InstanceConstructor] ExpressionVariables
# 49| 3: [ConstructorInitializer] call to constructor ExpressionVariables
# 49| 0: [LocalVariableDeclExpr] Int32 x
# 50| 4: [BlockStmt] {...}
# 51| 0: [ExprStmt] ...;
# 51| 0: [MethodCall] call to method WriteLine
# 51| -1: [TypeAccess] access to type Console
# 51| 0: [InterpolatedStringExpr] $"..."
# 51| 0: [StringLiteral] "x is "
# 51| 1: [LocalVariableAccess] access to local variable x
# 30| [Class] UnmanagedConstraint<>
#-----| 1: (Type parameters)
# 30| 0: [TypeParameter] T
# 34| [Class] EnumConstraint<>
#-----| 1: (Type parameters)
# 34| 0: [TypeParameter] T
# 38| [Class] DelegateConstraint<>
#-----| 1: (Type parameters)
# 38| 0: [TypeParameter] T

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,793 @@
CSharp7.cs:
# 7| [Class] Literals
# 9| 5: [Field] x
# 9| 1: [AssignExpr] ... = ...
# 9| 0: [IntLiteral] 11
# 9| 1: [FieldAccess] access to field x
# 10| 6: [Field] y
# 10| 1: [AssignExpr] ... = ...
# 10| 0: [IntLiteral] 123456
# 10| 1: [FieldAccess] access to field y
# 11| 7: [Field] z
# 11| 1: [AssignExpr] ... = ...
# 11| 0: [IntLiteral] 128
# 11| 1: [FieldAccess] access to field z
# 14| [Class] ExpressionBodiedMembers
# 16| 4: [Field] field
# 16| 1: [AssignExpr] ... = ...
# 16| 0: [IntLiteral] 0
# 16| 1: [FieldAccess] access to field field
# 17| 5: [Method] Foo
# 17| 4: [FieldAccess] access to field field
# 18| 6: [Property] P
# 18| 3: [Getter] get_P
# 18| 4: [IntLiteral] 5
# 19| 7: [Property] Q
# 21| 3: [Getter] get_Q
# 21| 4: [MethodCall] call to method Foo
# 22| 4: [Setter] set_Q
#-----| 2: (Parameters)
# 22| 0: [Parameter] value
# 22| 4: [AssignExpr] ... = ...
# 22| 0: [ParameterAccess] access to parameter value
# 22| 1: [FieldAccess] access to field field
# 24| 8: [InstanceConstructor] ExpressionBodiedMembers
# 24| 3: [ConstructorInitializer] call to constructor ExpressionBodiedMembers
# 24| 0: [IntLiteral] 1
# 24| 4: [BlockStmt] {...}
# 25| 9: [InstanceConstructor] ExpressionBodiedMembers
#-----| 2: (Parameters)
# 25| 0: [Parameter] x
# 25| 4: [MethodCall] call to method Foo
# 26| 10: [Destructor] ~ExpressionBodiedMembers
# 26| 4: [MethodCall] call to method Foo
# 29| [Class] ThrowExpr
# 31| 5: [Method] Throw
#-----| 2: (Parameters)
# 31| 0: [Parameter] i
# 32| 4: [BlockStmt] {...}
# 33| 0: [ReturnStmt] return ...;
# 33| 0: [ConditionalExpr] ... ? ... : ...
# 33| 0: [GTExpr] ... > ...
# 33| 0: [ParameterAccess] access to parameter i
# 33| 1: [IntLiteral] 0
# 33| 1: [ParameterAccess] access to parameter i
# 33| 2: [ThrowExpr] throw ...
# 33| 0: [ObjectCreation] object creation of type ArgumentException
# 33| 0: [StringLiteral] "i"
# 37| [Class] OutVariables
# 39| 5: [Method] F
#-----| 2: (Parameters)
# 39| 0: [Parameter] x
# 40| 4: [BlockStmt] {...}
# 41| 0: [ExprStmt] ...;
# 41| 0: [AssignExpr] ... = ...
# 41| 0: [StringLiteral] "tainted"
# 41| 1: [ParameterAccess] access to parameter x
# 44| 6: [Method] G
#-----| 2: (Parameters)
# 44| 0: [Parameter] x
# 44| 1: [Parameter] y
# 45| 4: [BlockStmt] {...}
# 46| 0: [ExprStmt] ...;
# 46| 0: [AssignExpr] ... = ...
# 46| 0: [ParameterAccess] access to parameter x
# 46| 1: [ParameterAccess] access to parameter y
# 49| 7: [Method] G
# 50| 4: [BlockStmt] {...}
# 51| 0: [ExprStmt] ...;
# 51| 0: [MethodCall] call to method F
# 51| 0: [LocalVariableAccess,LocalVariableDeclExpr] String t1
# 52| 1: [ExprStmt] ...;
# 52| 0: [MethodCall] call to method F
# 52| 0: [LocalVariableAccess,LocalVariableDeclExpr] String t2
# 53| 2: [LocalVariableDeclStmt] ... ...;
# 53| 0: [LocalVariableDeclAndInitExpr] String t3 = ...
# 53| 0: [LocalVariableAccess] access to local variable t1
# 53| 1: [LocalVariableAccess] access to local variable t3
# 54| 3: [ExprStmt] ...;
# 54| 0: [MethodCall] call to method F
# 54| 0: [LocalVariableAccess] access to local variable t1
# 55| 4: [ExprStmt] ...;
# 55| 0: [AssignExpr] ... = ...
# 55| 0: [LocalVariableAccess] access to local variable t1
# 55| 1: [LocalVariableAccess] access to local variable t3
# 56| 5: [ExprStmt] ...;
# 56| 0: [AssignExpr] ... = ...
# 56| 0: [LocalVariableAccess] access to local variable t2
# 56| 1: [LocalVariableAccess] access to local variable t3
# 57| 6: [ExprStmt] ...;
# 57| 0: [MethodCall] call to method G
# 57| 0: [StringLiteral] "tainted"
# 57| 1: [LocalVariableAccess,LocalVariableDeclExpr] String t4
# 58| 7: [LocalVariableDeclStmt] ... ...;
# 58| 0: [LocalVariableDeclAndInitExpr] String t5 = ...
# 58| 0: [LocalVariableAccess] access to local variable t4
# 58| 1: [LocalVariableAccess] access to local variable t5
# 62| [Class] Tuples
# 64| 5: [Method] F
# 65| 4: [BlockStmt] {...}
# 66| 0: [ReturnStmt] return ...;
# 66| 0: [TupleExpr] (..., ...)
# 66| 0: [IntLiteral] 1
# 66| 1: [IntLiteral] 2
# 69| 6: [Method] Expressions
# 70| 4: [BlockStmt] {...}
# 71| 0: [ExprStmt] ...;
# 71| 0: [AssignExpr] ... = ...
# 71| 0: [MethodCall] call to method F
# 71| 1: [TupleExpr] (..., ...)
# 71| 0: [LocalVariableDeclExpr] Int32 x
# 71| 1: [LocalVariableDeclExpr] Int32 y
# 72| 1: [LocalVariableDeclStmt] ... ...;
# 72| 0: [LocalVariableDeclAndInitExpr] (Int32,Int32) z = ...
# 72| 0: [MethodCall] call to method F
# 72| 1: [LocalVariableAccess] access to local variable z
# 73| 2: [ExprStmt] ...;
# 73| 0: [AssignExpr] ... = ...
# 73| 0: [MethodCall] call to method F
# 73| 1: [TupleExpr] (..., ...)
# 73| 0: [LocalVariableAccess] access to local variable x
# 73| 1: [LocalVariableAccess] access to local variable y
# 74| 3: [ExprStmt] ...;
# 74| 0: [AssignExpr] ... = ...
# 74| 0: [FieldAccess] access to field Item1
# 74| -1: [MethodCall] call to method F
# 74| 1: [LocalVariableAccess] access to local variable x
# 75| 4: [ExprStmt] ...;
# 75| 0: [AssignExpr] ... = ...
# 75| 0: [TupleExpr] (..., ...)
# 75| 0: [IntLiteral] 1
# 75| 1: [IntLiteral] 2
# 75| 2: [IntLiteral] 3
# 75| 1: [TupleExpr] (..., ...)
# 75| 0: [LocalVariableAccess] access to local variable x
# 75| 1: [LocalVariableAccess] access to local variable y
# 75| 2: [FieldAccess] access to field Item1
# 75| -1: [LocalVariableAccess] access to local variable z
# 76| 5: [ExprStmt] ...;
# 76| 0: [AssignExpr] ... = ...
# 76| 0: [AssignExpr] ... = ...
# 76| 0: [TupleExpr] (..., ...)
# 76| 0: [IntLiteral] 1
# 76| 1: [IntLiteral] 2
# 76| 1: [TupleExpr] (..., ...)
# 76| 0: [LocalVariableAccess] access to local variable x
# 76| 1: [LocalVariableAccess] access to local variable y
# 76| 1: [TupleExpr] (..., ...)
# 76| 0: [LocalVariableAccess] access to local variable x
# 76| 1: [LocalVariableAccess] access to local variable y
# 77| 6: [ExprStmt] ...;
# 77| 0: [AssignExpr] ... = ...
# 77| 0: [TupleExpr] (..., ...)
# 77| 0: [IntLiteral] 1
# 77| 1: [LocalVariableAccess] access to local variable z
# 77| 1: [TupleExpr] (..., ...)
# 77| 0: [LocalVariableDeclExpr] Int32 a
# 77| 1: [TupleExpr] (..., ...)
# 77| 0: [LocalVariableDeclExpr] Int32 b
# 77| 1: [LocalVariableDeclExpr] Int32 c
# 78| 7: [ExprStmt] ...;
# 78| 0: [AssignExpr] ... = ...
# 78| 0: [TupleExpr] (..., ...)
# 78| 0: [LocalVariableAccess] access to local variable b
# 78| 1: [TupleExpr] (..., ...)
# 78| 0: [LocalVariableAccess] access to local variable c
# 78| 1: [LocalVariableAccess] access to local variable a
# 78| 1: [TupleExpr] (..., ...)
# 78| 0: [LocalVariableAccess] access to local variable a
# 78| 1: [TupleExpr] (..., ...)
# 78| 0: [LocalVariableAccess] access to local variable b
# 78| 1: [LocalVariableAccess] access to local variable c
# 79| 8: [ExprStmt] ...;
# 79| 0: [AssignExpr] ... = ...
# 79| 0: [TupleExpr] (..., ...)
# 79| 0: [StringLiteral] ""
# 79| 1: [LocalVariableAccess] access to local variable x
# 79| 1: [TupleExpr] (..., ...)
# 79| 0: [LocalVariableDeclExpr] String i
# 79| 1: [LocalVariableDeclExpr] Int32 j
# 82| 7: [Method] I
#-----| 2: (Parameters)
# 82| 0: [Parameter] x
# 83| 4: [BlockStmt] {...}
# 84| 0: [ReturnStmt] return ...;
# 84| 0: [FieldAccess] access to field a
# 84| -1: [TupleExpr] (..., ...)
# 84| 0: [ParameterAccess] access to parameter x
# 84| 1: [IntLiteral] 2
# 87| 8: [Method] TaintFlow
# 88| 4: [BlockStmt] {...}
# 89| 0: [LocalVariableDeclStmt] ... ...;
# 89| 0: [LocalVariableDeclAndInitExpr] (String,String) t1 = ...
# 89| 0: [TupleExpr] (..., ...)
# 89| 0: [StringLiteral] "tainted"
# 89| 1: [StringLiteral] "X2"
# 89| 1: [LocalVariableAccess] access to local variable t1
# 90| 1: [ExprStmt] ...;
# 90| 0: [AssignExpr] ... = ...
# 90| 0: [LocalVariableAccess] access to local variable t1
# 90| 1: [TupleExpr] (..., ...)
# 90| 0: [LocalVariableDeclExpr] String t2
# 90| 1: [LocalVariableDeclExpr] String t3
# 91| 2: [LocalVariableDeclStmt] ... ...;
# 91| 0: [LocalVariableDeclAndInitExpr] String t4 = ...
# 91| 0: [LocalVariableAccess] access to local variable t3
# 91| 1: [LocalVariableAccess] access to local variable t4
# 92| 3: [LocalVariableDeclStmt] ... ...;
# 92| 0: [LocalVariableDeclAndInitExpr] String t5 = ...
# 92| 0: [MethodCall] call to method I
# 92| 0: [FieldAccess] access to field Item1
# 92| -1: [LocalVariableAccess] access to local variable t1
# 92| 1: [LocalVariableAccess] access to local variable t5
# 95| 9: [Method] TupleExprNode
# 96| 4: [BlockStmt] {...}
# 97| 0: [LocalVariableDeclStmt] ... ...;
# 97| 0: [LocalVariableDeclAndInitExpr] (Int32,String) m1 = ...
# 97| 0: [TupleExpr] (..., ...)
# 97| 0: [IntLiteral] 1
# 97| 1: [StringLiteral] "TupleExprNode1"
# 97| 1: [LocalVariableAccess] access to local variable m1
# 98| 1: [LocalVariableDeclStmt] ... ...;
# 98| 0: [LocalVariableDeclAndInitExpr] (Int32,(String,Int32)) m2 = ...
# 98| 0: [TupleExpr] (..., ...)
# 98| 0: [IntLiteral] 1
# 98| 1: [TupleExpr] (..., ...)
# 98| 0: [StringLiteral] "TupleExprNode2"
# 98| 1: [IntLiteral] 2
# 98| 1: [LocalVariableAccess] access to local variable m2
# 101| 10: [Method] TupleMemberAccess
# 102| 4: [BlockStmt] {...}
# 103| 0: [LocalVariableDeclStmt] ... ...;
# 103| 0: [LocalVariableDeclAndInitExpr] String m1 = ...
# 103| 0: [FieldAccess] access to field Item1
# 103| -1: [TupleExpr] (..., ...)
# 103| 0: [StringLiteral] "TupleMemberAccess1"
# 103| 1: [IntLiteral] 0
# 103| 1: [LocalVariableAccess] access to local variable m1
# 104| 1: [LocalVariableDeclStmt] ... ...;
# 104| 0: [LocalVariableDeclAndInitExpr] (String,Int32) m2 = ...
# 104| 0: [FieldAccess] access to field Item2
# 104| -1: [TupleExpr] (..., ...)
# 104| 0: [IntLiteral] 0
# 104| 1: [TupleExpr] (..., ...)
# 104| 0: [StringLiteral] "TupleMemberAccess2"
# 104| 1: [IntLiteral] 1
# 104| 1: [LocalVariableAccess] access to local variable m2
# 107| 11: [Method] DefUse
# 108| 4: [BlockStmt] {...}
# 109| 0: [ExprStmt] ...;
# 109| 0: [AssignExpr] ... = ...
# 109| 0: [TupleExpr] (..., ...)
# 109| 0: [StringLiteral] "DefUse1"
# 109| 1: [TupleExpr] (..., ...)
# 109| 0: [IntLiteral] 0
# 109| 1: [IntLiteral] 1
# 109| 1: [TupleExpr] (..., ...)
# 109| 0: [LocalVariableDeclExpr] String m1
# 109| 1: [LocalVariableDeclExpr] (Int32,Int32) m2
# 110| 1: [LocalVariableDeclStmt] ... ...;
# 110| 0: [LocalVariableDeclExpr] String m3
# 111| 2: [LocalVariableDeclStmt] ... ...;
# 111| 0: [LocalVariableDeclExpr] Int32 m4
# 111| 1: [LocalVariableDeclExpr] Int32 m5
# 112| 3: [ExprStmt] ...;
# 112| 0: [AssignExpr] ... = ...
# 112| 0: [TupleExpr] (..., ...)
# 112| 0: [LocalVariableAccess] access to local variable m1
# 112| 1: [LocalVariableAccess] access to local variable m2
# 112| 1: [TupleExpr] (..., ...)
# 112| 0: [LocalVariableAccess] access to local variable m3
# 112| 1: [TupleExpr] (..., ...)
# 112| 0: [LocalVariableAccess] access to local variable m4
# 112| 1: [LocalVariableAccess] access to local variable m5
# 113| 4: [LocalVariableDeclStmt] ... ...;
# 113| 0: [LocalVariableDeclAndInitExpr] Int32 m6 = ...
# 113| 0: [LocalVariableAccess] access to local variable m4
# 113| 1: [LocalVariableAccess] access to local variable m6
# 114| 5: [ExprStmt] ...;
# 114| 0: [AssignExpr] ... = ...
# 114| 0: [AssignExpr] ... = ...
# 114| 0: [TupleExpr] (..., ...)
# 114| 0: [StringLiteral] "DefUse2"
# 114| 1: [TupleExpr] (..., ...)
# 114| 0: [IntLiteral] 0
# 114| 1: [IntLiteral] 1
# 114| 1: [TupleExpr] (..., ...)
# 114| 0: [LocalVariableAccess] access to local variable m1
# 114| 1: [LocalVariableAccess] access to local variable m2
# 114| 1: [TupleExpr] (..., ...)
# 114| 0: [LocalVariableDeclExpr] String m7
# 114| 1: [TupleExpr] (..., ...)
# 114| 0: [LocalVariableDeclExpr] Int32 m8
# 114| 1: [LocalVariableDeclExpr] Int32 m9
# 115| 6: [LocalVariableDeclStmt] ... ...;
# 115| 0: [LocalVariableDeclAndInitExpr] Int32 m10 = ...
# 115| 0: [LocalVariableAccess] access to local variable m9
# 115| 1: [LocalVariableAccess] access to local variable m10
# 118| 7: [ExprStmt] ...;
# 118| 0: [AssignExpr] ... = ...
# 118| 0: [IntLiteral] 0
# 118| 1: [FieldAccess] access to field Item2
# 118| -1: [LocalVariableAccess] access to local variable m2
# 119| 8: [LocalVariableDeclStmt] ... ...;
# 119| 0: [LocalVariableDeclAndInitExpr] Int32 m11 = ...
# 119| 0: [FieldAccess] access to field Item1
# 119| -1: [LocalVariableAccess] access to local variable m2
# 119| 1: [LocalVariableAccess] access to local variable m11
# 122| 9: [LocalVariableDeclStmt] ... ...;
# 122| 0: [LocalVariableDeclExpr] String m12
# 123| 10: [LocalVariableDeclStmt] ... ...;
# 123| 0: [LocalVariableDeclAndInitExpr] String m13 = ...
# 123| 0: [AssignExpr] ... = ...
# 123| 0: [StringLiteral] "DefUse3"
# 123| 1: [LocalVariableAccess] access to local variable m12
# 123| 1: [LocalVariableAccess] access to local variable m13
# 127| [Class] LocalFunctions
# 129| 5: [Method] Main
# 130| 4: [BlockStmt] {...}
# 131| 0: [LocalFunctionStmt] f1(...)
# 131| 0: [LocalFunction] f1
#-----| 2: (Parameters)
# 131| 0: [Parameter] x
# 131| 4: [BlockStmt] {...}
# 131| 0: [ReturnStmt] return ...;
# 131| 0: [AddExpr] ... + ...
# 131| 0: [ParameterAccess] access to parameter x
# 131| 1: [IntLiteral] 1
# 133| 1: [LocalFunctionStmt] f2(...)
# 133| 0: [LocalFunction] f2
#-----| 1: (Type parameters)
# 133| 0: [TypeParameter] T
# 133| 1: [TypeParameter] U
#-----| 2: (Parameters)
# 133| 0: [Parameter] t
# 133| 1: [Parameter] u
# 133| 4: [BlockStmt] {...}
# 133| 0: [ReturnStmt] return ...;
# 133| 0: [ParameterAccess] access to parameter t
# 135| 2: [LocalVariableDeclStmt] ... ...;
# 135| 0: [LocalVariableDeclAndInitExpr] Func<Int32> f4 = ...
# 135| 0: [ImplicitDelegateCreation] delegate creation of type Func<Int32>
# 135| 0: [LocalFunctionAccess] access to local function f3
# 135| 1: [LocalVariableAccess] access to local variable f4
# 137| 3: [LocalFunctionStmt] f3(...)
# 137| 0: [LocalFunction] f3
# 137| 4: [IntLiteral] 2
# 139| 4: [LocalVariableDeclStmt] ... ...;
# 139| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Int32> f5 = ...
# 139| 0: [LambdaExpr] (...) => ...
#-----| 2: (Parameters)
# 139| 0: [Parameter] x
# 139| 4: [AddExpr] ... + ...
# 139| 0: [ParameterAccess] access to parameter x
# 139| 1: [IntLiteral] 1
# 139| 1: [LocalVariableAccess] access to local variable f5
# 141| 5: [LocalFunctionStmt] f6(...)
# 141| 0: [LocalFunction] f6
#-----| 2: (Parameters)
# 141| 0: [Parameter] x
# 141| 4: [ConditionalExpr] ... ? ... : ...
# 141| 0: [GTExpr] ... > ...
# 141| 0: [ParameterAccess] access to parameter x
# 141| 1: [IntLiteral] 0
# 141| 1: [AddExpr] ... + ...
# 141| 0: [IntLiteral] 1
# 141| 1: [LocalFunctionCall] call to local function f7
# 141| -1: [LocalFunctionAccess] access to local function f7
# 141| 0: [SubExpr] ... - ...
# 141| 0: [ParameterAccess] access to parameter x
# 141| 1: [IntLiteral] 1
# 141| 2: [IntLiteral] 0
# 143| 6: [LocalFunctionStmt] f7(...)
# 143| 0: [LocalFunction] f7
#-----| 2: (Parameters)
# 143| 0: [Parameter] x
# 143| 4: [LocalFunctionCall] call to local function f6
# 143| -1: [LocalFunctionAccess] access to local function f6
# 143| 0: [ParameterAccess] access to parameter x
# 145| 7: [LocalFunctionStmt] f8(...)
# 145| 0: [LocalFunction] f8
# 146| 4: [BlockStmt] {...}
# 147| 0: [LocalFunctionStmt] f9(...)
# 147| 0: [LocalFunction] f9
#-----| 2: (Parameters)
# 147| 0: [Parameter] x
# 147| 4: [LocalFunctionCall] call to local function f7
# 147| -1: [LocalFunctionAccess] access to local function f7
# 147| 0: [ParameterAccess] access to parameter x
# 148| 1: [ReturnStmt] return ...;
# 148| 0: [LocalFunctionCall] call to local function f9
# 148| -1: [LocalFunctionAccess] access to local function f9
# 148| 0: [IntLiteral] 1
# 151| 8: [LocalVariableDeclStmt] ... ...;
# 151| 0: [LocalVariableDeclAndInitExpr] Action a = ...
# 151| 0: [LambdaExpr] (...) => ...
# 151| 4: [BlockStmt] {...}
# 152| 0: [LocalFunctionStmt] f9(...)
# 152| 0: [LocalFunction] f9
# 152| 4: [IntLiteral] 0
# 151| 1: [LocalVariableAccess] access to local variable a
# 155| 9: [ReturnStmt] return ...;
# 155| 0: [LocalFunctionCall] call to local function f1
# 155| -1: [LocalFunctionAccess] access to local function f1
# 155| 0: [IntLiteral] 2
# 158| 6: [Method] Generics
# 159| 4: [BlockStmt] {...}
# 160| 0: [LocalFunctionStmt] f(...)
# 160| 0: [LocalFunction] f
#-----| 1: (Type parameters)
# 160| 0: [TypeParameter] T
# 160| 4: [IntLiteral] 1
# 161| 1: [LocalFunctionStmt] g(...)
# 161| 0: [LocalFunction] g
#-----| 1: (Type parameters)
# 161| 0: [TypeParameter] T
#-----| 2: (Parameters)
# 161| 0: [Parameter] t
# 161| 4: [ParameterAccess] access to parameter t
# 163| 2: [LocalFunctionStmt] h(...)
# 163| 0: [LocalFunction] h
#-----| 1: (Type parameters)
# 163| 0: [TypeParameter] T
# 163| 1: [TypeParameter] U
#-----| 2: (Parameters)
# 163| 0: [Parameter] t
# 163| 1: [Parameter] u
# 164| 4: [BlockStmt] {...}
# 165| 0: [LocalFunctionStmt] f2(...)
# 165| 0: [LocalFunction] f2
#-----| 1: (Type parameters)
# 165| 0: [TypeParameter] S
#-----| 2: (Parameters)
# 165| 0: [Parameter] s
# 165| 1: [Parameter] _t
# 165| 4: [LocalFunctionCall] call to local function f
# 165| -1: [LocalFunctionAccess] access to local function f
# 166| 1: [ExprStmt] ...;
# 166| 0: [LocalFunctionCall] call to local function f
# 166| -1: [LocalFunctionAccess] access to local function f
# 167| 2: [ReturnStmt] return ...;
# 167| 0: [LocalFunctionCall] call to local function g
# 167| -1: [LocalFunctionAccess] access to local function g
# 167| 0: [ParameterAccess] access to parameter u
# 170| 3: [ExprStmt] ...;
# 170| 0: [LocalFunctionCall] call to local function h
# 170| -1: [LocalFunctionAccess] access to local function h
# 170| 0: [IntLiteral] 0
# 170| 1: [IntLiteral] 0
# 171| 4: [ExprStmt] ...;
# 171| 0: [LocalFunctionCall] call to local function h
# 171| -1: [LocalFunctionAccess] access to local function h
# 171| 0: [StringLiteral] ""
# 171| 1: [BoolLiteral] true
# 174| 7: [Method] GlobalFlow
# 175| 4: [BlockStmt] {...}
# 176| 0: [LocalVariableDeclStmt] ... ...;
# 176| 0: [LocalVariableDeclAndInitExpr] String src = ...
# 176| 0: [StringLiteral] "tainted"
# 176| 1: [LocalVariableAccess] access to local variable src
# 177| 1: [LocalFunctionStmt] f(...)
# 177| 0: [LocalFunction] f
#-----| 2: (Parameters)
# 177| 0: [Parameter] s
# 177| 4: [AddExpr] ... + ...
# 177| 0: [LocalFunctionCall] call to local function g
# 177| -1: [LocalFunctionAccess] access to local function g
# 177| 0: [ParameterAccess] access to parameter s
# 177| 1: [StringLiteral] ""
# 178| 2: [LocalFunctionStmt] g(...)
# 178| 0: [LocalFunction] g
#-----| 2: (Parameters)
# 178| 0: [Parameter] s
# 178| 4: [ParameterAccess] access to parameter s
# 179| 3: [LocalFunctionStmt] h(...)
# 179| 0: [LocalFunction] h
#-----| 2: (Parameters)
# 179| 0: [Parameter] s
# 179| 4: [BlockStmt] {...}
# 179| 0: [ReturnStmt] return ...;
# 179| 0: [ParameterAccess] access to parameter s
# 181| 4: [LocalVariableDeclStmt] ... ...;
# 181| 0: [LocalVariableDeclAndInitExpr] String sink1 = ...
# 181| 0: [LocalFunctionCall] call to local function f
# 181| -1: [LocalFunctionAccess] access to local function f
# 181| 0: [LocalVariableAccess] access to local variable src
# 181| 1: [LocalVariableAccess] access to local variable sink1
# 182| 5: [LocalVariableDeclStmt] ... ...;
# 182| 0: [LocalVariableDeclAndInitExpr] String sink2 = ...
# 182| 0: [LocalFunctionCall] call to local function g
# 182| -1: [LocalFunctionAccess] access to local function g
# 182| 0: [LocalVariableAccess] access to local variable src
# 182| 1: [LocalVariableAccess] access to local variable sink2
# 183| 6: [LocalVariableDeclStmt] ... ...;
# 183| 0: [LocalVariableDeclAndInitExpr] String sink3 = ...
# 183| 0: [LocalFunctionCall] call to local function h
# 183| -1: [LocalFunctionAccess] access to local function h
# 183| 0: [LocalVariableAccess] access to local variable src
# 183| 1: [LocalVariableAccess] access to local variable sink3
# 187| [Class] Refs
# 189| 5: [Method] F1
# 190| 4: [BlockStmt] {...}
# 191| 0: [LocalVariableDeclStmt] ... ...;
# 191| 0: [LocalVariableDeclAndInitExpr] Int32 v1 = ...
# 191| 0: [IntLiteral] 2
# 191| 1: [LocalVariableAccess] access to local variable v1
# 192| 1: [LocalVariableDeclStmt] ... ...;
# 192| 0: [LocalVariableDeclAndInitExpr] Int32 r1 = ...
# 192| 0: [RefExpr] ref ...
# 192| 0: [LocalVariableAccess] access to local variable v1
# 192| 1: [LocalVariableAccess] access to local variable r1
# 193| 2: [LocalVariableDeclStmt] ... ...;
# 193| 0: [LocalVariableDeclAndInitExpr] Int32[] array = ...
# 193| 0: [ArrayCreation] array creation of type Int32[]
# 193| 0: [IntLiteral] 10
# 193| 1: [LocalVariableAccess] access to local variable array
# 194| 3: [ExprStmt] ...;
# 194| 0: [AssignExpr] ... = ...
# 194| 0: [IntLiteral] 3
# 194| 1: [LocalVariableAccess] access to local variable r1
# 195| 4: [ExprStmt] ...;
# 195| 0: [AssignExpr] ... = ...
# 195| 0: [ArrayAccess] access to array element
# 195| -1: [LocalVariableAccess] access to local variable array
# 195| 0: [IntLiteral] 1
# 195| 1: [LocalVariableAccess] access to local variable r1
# 196| 5: [LocalVariableDeclStmt] ... ...;
# 196| 0: [LocalVariableDeclAndInitExpr] Int32 r2 = ...
# 196| 0: [RefExpr] ref ...
# 196| 0: [ArrayAccess] access to array element
# 196| -1: [LocalVariableAccess] access to local variable array
# 196| 0: [IntLiteral] 3
# 196| 1: [LocalVariableAccess] access to local variable r2
# 197| 6: [LocalVariableDeclStmt] ... ...;
# 197| 0: [LocalVariableDeclAndInitExpr] Int32 r3 = ...
# 197| 0: [RefExpr] ref ...
# 197| 0: [LocalVariableAccess] access to local variable r1
# 197| 1: [LocalVariableAccess] access to local variable r3
# 198| 7: [ExprStmt] ...;
# 198| 0: [AssignExpr] ... = ...
# 198| 0: [MethodCall] call to method F2
# 198| 0: [LocalVariableAccess] access to local variable v1
# 198| 1: [LocalVariableAccess] access to local variable v1
# 199| 8: [LocalVariableDeclStmt] ... ...;
# 199| 0: [LocalVariableDeclAndInitExpr] Int32 r4 = ...
# 199| 0: [RefExpr] ref ...
# 199| 0: [MethodCall] call to method F2
# 199| 0: [LocalVariableAccess] access to local variable r1
# 199| 1: [LocalVariableAccess] access to local variable r4
# 200| 9: [ExprStmt] ...;
# 200| 0: [AssignExpr] ... = ...
# 200| 0: [IntLiteral] 3
# 200| 1: [MethodCall] call to method F2
# 200| 0: [LocalVariableAccess] access to local variable r1
# 203| 6: [Method] F2
#-----| 2: (Parameters)
# 203| 0: [Parameter] p
# 204| 4: [BlockStmt] {...}
# 205| 0: [LocalFunctionStmt] F3(...)
# 205| 0: [LocalFunction] F3
#-----| 2: (Parameters)
# 205| 0: [Parameter] q
# 205| 4: [BlockStmt] {...}
# 205| 0: [ReturnStmt] return ...;
# 205| 0: [RefExpr] ref ...
# 205| 0: [ParameterAccess] access to parameter q
# 206| 1: [ReturnStmt] return ...;
# 206| 0: [RefExpr] ref ...
# 206| 0: [ParameterAccess] access to parameter p
# 209| 7: [DelegateType] RefFn
#-----| 2: (Parameters)
# 209| 0: [Parameter] p
# 212| [Class] Discards
# 214| 5: [Method] f
#-----| 2: (Parameters)
# 214| 0: [Parameter] x
# 215| 4: [BlockStmt] {...}
# 216| 0: [ExprStmt] ...;
# 216| 0: [AssignExpr] ... = ...
# 216| 0: [BoolLiteral] false
# 216| 1: [ParameterAccess] access to parameter x
# 217| 1: [ReturnStmt] return ...;
# 217| 0: [TupleExpr] (..., ...)
# 217| 0: [IntLiteral] 0
# 217| 1: [DoubleLiteral] 0
# 220| 6: [Method] Test
# 221| 4: [BlockStmt] {...}
# 222| 0: [ExprStmt] ...;
# 222| 0: [AssignExpr] ... = ...
# 222| 0: [MethodCall] call to method f
# 222| 0: [DiscardExpr] _
# 222| 1: [DiscardExpr] _
# 223| 1: [ExprStmt] ...;
# 223| 0: [AssignExpr] ... = ...
# 223| 0: [MethodCall] call to method f
# 223| 0: [DiscardExpr] _
# 223| 1: [TupleExpr] (..., ...)
# 223| 0: [DiscardExpr] _
# 223| 1: [DiscardExpr] _
# 224| 2: [ExprStmt] ...;
# 224| 0: [AssignExpr] ... = ...
# 224| 0: [MethodCall] call to method f
# 224| 0: [DiscardExpr] _
# 224| 1: [TupleExpr] (..., ...)
# 224| 0: [LocalVariableDeclExpr] Int32 x
# 224| 1: [DiscardExpr] _
# 225| 3: [ExprStmt] ...;
# 225| 0: [AssignExpr] ... = ...
# 225| 0: [MethodCall] call to method f
# 225| 0: [LocalVariableAccess,LocalVariableDeclExpr] Boolean z
# 225| 1: [TupleExpr] (..., ...)
# 225| 0: [DiscardExpr] _
# 225| 1: [LocalVariableDeclExpr] Double y
# 229| [Class] Patterns
# 231| 5: [Method] Test
# 232| 4: [BlockStmt] {...}
# 233| 0: [LocalVariableDeclStmt] ... ...;
# 233| 0: [LocalVariableDeclAndInitExpr] Object o = ...
# 233| 0: [NullLiteral] null
# 233| 1: [LocalVariableAccess] access to local variable o
# 234| 1: [IfStmt] if (...) ...
# 234| 0: [LogicalAndExpr] ... && ...
# 234| 0: [IsExpr] ... is ...
# 234| 0: [LocalVariableAccess] access to local variable o
# 234| 1: [VariablePatternExpr] Int32 i1
# 234| 1: [GTExpr] ... > ...
# 234| 0: [LocalVariableAccess] access to local variable i1
# 234| 1: [IntLiteral] 0
# 235| 1: [BlockStmt] {...}
# 236| 0: [ExprStmt] ...;
# 236| 0: [MethodCall] call to method WriteLine
# 236| -1: [TypeAccess] access to type Console
# 236| 0: [InterpolatedStringExpr] $"..."
# 236| 0: [StringLiteral] "int "
# 236| 1: [LocalVariableAccess] access to local variable i1
# 238| 2: [IfStmt] if (...) ...
# 238| 0: [IsExpr] ... is ...
# 238| 0: [LocalVariableAccess] access to local variable o
# 238| 1: [VariablePatternExpr] String s1
# 239| 1: [BlockStmt] {...}
# 240| 0: [ExprStmt] ...;
# 240| 0: [MethodCall] call to method WriteLine
# 240| -1: [TypeAccess] access to type Console
# 240| 0: [InterpolatedStringExpr] $"..."
# 240| 0: [StringLiteral] "string "
# 240| 1: [LocalVariableAccess] access to local variable s1
# 242| 2: [IfStmt] if (...) ...
# 242| 0: [IsExpr] ... is ...
# 242| 0: [LocalVariableAccess] access to local variable o
# 242| 1: [TypeAccessPatternExpr] access to type Double
# 243| 1: [BlockStmt] {...}
# 245| 2: [IfStmt] if (...) ...
# 245| 0: [IsExpr] ... is ...
# 245| 0: [LocalVariableAccess] access to local variable o
# 245| 1: [VariablePatternExpr] Object v1
# 246| 1: [BlockStmt] {...}
# 249| 2: [SwitchStmt] switch (...) {...}
# 249| 0: [LocalVariableAccess] access to local variable o
# 251| 0: [ConstCase] case ...:
# 251| 0: [ConstantPatternExpr,StringLiteral] "xyz"
# 252| 1: [BreakStmt] break;
# 253| 2: [ConstCase] case ...:
# 253| 0: [ConstantPatternExpr,StringLiteral] ""
# 253| 1: [LTExpr] ... < ...
# 253| 0: [IntLiteral] 1
# 253| 1: [IntLiteral] 2
# 254| 3: [BreakStmt] break;
# 255| 4: [ConstCase] case ...:
# 255| 0: [ConstantPatternExpr,StringLiteral] "x"
# 255| 1: [IsExpr] ... is ...
# 255| 0: [LocalVariableAccess] access to local variable o
# 255| 1: [VariablePatternExpr] String s4
# 256| 5: [ExprStmt] ...;
# 256| 0: [MethodCall] call to method WriteLine
# 256| -1: [TypeAccess] access to type Console
# 256| 0: [InterpolatedStringExpr] $"..."
# 256| 0: [StringLiteral] "x "
# 256| 1: [LocalVariableAccess] access to local variable s4
# 257| 6: [BreakStmt] break;
# 258| 7: [CaseStmt] case ...:
# 258| 0: [VariablePatternExpr] Int32 i2
# 258| 1: [GTExpr] ... > ...
# 258| 0: [LocalVariableAccess] access to local variable i2
# 258| 1: [IntLiteral] 0
# 259| 8: [ExprStmt] ...;
# 259| 0: [MethodCall] call to method WriteLine
# 259| -1: [TypeAccess] access to type Console
# 259| 0: [InterpolatedStringExpr] $"..."
# 259| 0: [StringLiteral] "positive "
# 259| 1: [LocalVariableAccess] access to local variable i2
# 260| 9: [BreakStmt] break;
# 261| 10: [CaseStmt] case ...:
# 261| 0: [VariablePatternExpr] Int32 i3
# 262| 11: [ExprStmt] ...;
# 262| 0: [MethodCall] call to method WriteLine
# 262| -1: [TypeAccess] access to type Console
# 262| 0: [InterpolatedStringExpr] $"..."
# 262| 0: [StringLiteral] "int "
# 262| 1: [LocalVariableAccess] access to local variable i3
# 263| 12: [BreakStmt] break;
# 264| 13: [CaseStmt] case ...:
# 264| 0: [VariablePatternExpr] String s2
# 265| 14: [ExprStmt] ...;
# 265| 0: [MethodCall] call to method WriteLine
# 265| -1: [TypeAccess] access to type Console
# 265| 0: [InterpolatedStringExpr] $"..."
# 265| 0: [StringLiteral] "string "
# 265| 1: [LocalVariableAccess] access to local variable s2
# 266| 15: [BreakStmt] break;
# 267| 16: [CaseStmt] case ...:
# 267| 0: [TypeAccessPatternExpr] access to type Double
# 268| 17: [ExprStmt] ...;
# 268| 0: [MethodCall] call to method WriteLine
# 268| -1: [TypeAccess] access to type Console
# 268| 0: [StringLiteral] "Double"
# 269| 18: [BreakStmt] break;
# 270| 19: [CaseStmt] case ...:
# 270| 0: [VariablePatternExpr] Object v2
# 271| 20: [BreakStmt] break;
# 272| 21: [DefaultCase] default:
# 273| 22: [ExprStmt] ...;
# 273| 0: [MethodCall] call to method WriteLine
# 273| -1: [TypeAccess] access to type Console
# 273| 0: [StringLiteral] "Something else"
# 274| 23: [BreakStmt] break;
# 279| [Class] ForeachStatements
# 281| 5: [Method] Test
# 282| 4: [BlockStmt] {...}
# 283| 0: [LocalVariableDeclStmt] ... ...;
# 283| 0: [LocalVariableDeclAndInitExpr] Dictionary<Int32,String> dict = ...
# 283| 0: [ObjectCreation] object creation of type Dictionary<Int32,String>
# 283| 1: [LocalVariableAccess] access to local variable dict
# 284| 1: [LocalVariableDeclStmt] ... ...;
# 284| 0: [LocalVariableDeclAndInitExpr] IEnumerable<(Int32,String)> list = ...
# 284| 0: [MethodCall] call to method Select
# 284| -1: [LocalVariableAccess] access to local variable dict
# 284| 0: [LambdaExpr] (...) => ...
#-----| 2: (Parameters)
# 284| 0: [Parameter] item
# 284| 4: [TupleExpr] (..., ...)
# 284| 0: [PropertyCall] access to property Key
# 284| -1: [ParameterAccess] access to parameter item
# 284| 1: [PropertyCall] access to property Value
# 284| -1: [ParameterAccess] access to parameter item
# 284| 1: [LocalVariableAccess] access to local variable list
# 286| 2: [ForeachStmt] foreach (... ... in ...) ...
# 286| 0: [TupleExpr] (..., ...)
# 286| 0: [LocalVariableDeclExpr] Int32 a
# 286| 1: [LocalVariableDeclExpr] String b
# 286| 1: [LocalVariableAccess] access to local variable list
# 286| 2: [BlockStmt] {...}
# 288| 3: [ForeachStmt] foreach (... ... in ...) ...
# 288| 0: [TupleExpr] (..., ...)
# 288| 0: [LocalVariableDeclExpr] Int32 a
# 288| 1: [LocalVariableDeclExpr] String b
# 288| 1: [LocalVariableAccess] access to local variable list
# 288| 2: [BlockStmt] {...}
# 290| 4: [ForeachStmt] foreach (... ... in ...) ...
# 290| 0: [TupleExpr] (..., ...)
# 290| 0: [LocalVariableDeclExpr] Int32 a
# 290| 1: [LocalVariableDeclExpr] String b
# 290| 1: [LocalVariableAccess] access to local variable list
# 290| 2: [BlockStmt] {...}
# 294| [Class] ForLoops
# 296| 5: [Method] Test
# 297| 4: [BlockStmt] {...}
# 298| 0: [ForStmt] for (...;...;...) ...
# 298| -1: [LocalVariableDeclAndInitExpr] Int32 x = ...
# 298| 0: [IntLiteral] 0
# 298| 1: [LocalVariableAccess] access to local variable x
# 298| 0: [LogicalAndExpr] ... && ...
# 298| 0: [LTExpr] ... < ...
# 298| 0: [LocalVariableAccess] access to local variable x
# 298| 1: [IntLiteral] 10
# 298| 1: [IsExpr] ... is ...
# 298| 0: [LocalVariableAccess] access to local variable x
# 298| 1: [VariablePatternExpr] Int32 y
# 298| 1: [PreIncrExpr] ++...
# 298| 0: [LocalVariableAccess] access to local variable x
# 299| 2: [BlockStmt] {...}
# 300| 0: [ExprStmt] ...;
# 300| 0: [MethodCall] call to method WriteLine
# 300| -1: [TypeAccess] access to type Console
# 300| 0: [LocalVariableAccess] access to local variable y

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,403 @@
definitions.cs:
# 4| [NamespaceDeclaration] namespace ... { ... }
# 6| 1: [Class] StaticClass
# 8| 4: [ExtensionMethod] ExtensionMethod
#-----| 2: (Parameters)
# 8| 0: [Parameter] c1
# 8| 1: [Parameter] args
# 9| 4: [BlockStmt] {...}
# 13| 2: [Enum] Enumeration
# 15| 5: [Field] e1
# 15| 1: [MemberConstantAccess] access to constant e1
# 15| 6: [Field] e2
# 15| 1: [MemberConstantAccess] access to constant e2
# 15| 7: [Field] e3
# 18| 3: [Class] C1
# 20| 4: [InstanceConstructor] C1
#-----| 2: (Parameters)
# 20| 0: [Parameter] args
# 20| 4: [BlockStmt] {...}
# 22| 5: [Field] field1
# 24| 6: [Property] property1
# 26| 3: [Getter] get_property1
# 26| 4: [BlockStmt] {...}
# 26| 0: [ReturnStmt] return ...;
# 26| 0: [FieldAccess] access to field field1
# 27| 4: [Setter] set_property1
#-----| 2: (Parameters)
# 27| 0: [Parameter] value
# 27| 4: [BlockStmt] {...}
# 27| 0: [ExprStmt] ...;
# 27| 0: [AssignExpr] ... = ...
# 27| 0: [ParameterAccess] access to parameter value
# 27| 1: [FieldAccess] access to field field1
# 30| 7: [Method] f1
#-----| 2: (Parameters)
# 30| 0: [Parameter] args
# 31| 4: [BlockStmt] {...}
# 32| 0: [LocalVariableDeclStmt] ... ...;
# 32| 0: [LocalVariableDeclAndInitExpr] C1 qualifier = ...
# 32| 0: [ThisAccess] this access
# 32| 1: [LocalVariableAccess] access to local variable qualifier
# 35| 1: [ExprStmt] ...;
# 35| 0: [MethodCall] call to method f1
# 36| 2: [ExprStmt] ...;
# 36| 0: [MethodCall] call to method f1
# 36| 0: [IntLiteral] 1
# 37| 3: [ExprStmt] ...;
# 37| 0: [MethodCall] call to method f1
# 37| 0: [IntLiteral] 1
# 37| 1: [IntLiteral] 2
# 39| 4: [ExprStmt] ...;
# 39| 0: [MethodCall] call to method f1
# 39| -1: [ThisAccess] this access
# 40| 5: [ExprStmt] ...;
# 40| 0: [MethodCall] call to method f1
# 40| -1: [ThisAccess] this access
# 40| 0: [IntLiteral] 1
# 41| 6: [ExprStmt] ...;
# 41| 0: [MethodCall] call to method f1
# 41| -1: [ThisAccess] this access
# 41| 0: [IntLiteral] 1
# 41| 1: [IntLiteral] 2
# 43| 7: [ExprStmt] ...;
# 43| 0: [MethodCall] call to method ExtensionMethod
# 43| -1: [ThisAccess] this access
# 44| 8: [ExprStmt] ...;
# 44| 0: [MethodCall] call to method ExtensionMethod
# 44| -1: [ThisAccess] this access
# 44| 0: [CastExpr] (...) ...
# 44| 0: [IntLiteral] 1
# 45| 9: [ExprStmt] ...;
# 45| 0: [MethodCall] call to method ExtensionMethod
# 45| -1: [ThisAccess] this access
# 45| 0: [CastExpr] (...) ...
# 45| 0: [IntLiteral] 1
# 45| 1: [CastExpr] (...) ...
# 45| 0: [IntLiteral] 2
# 47| 10: [ExprStmt] ...;
# 47| 0: [MethodCall] call to method GenericFn
# 47| 0: [IntLiteral] 1
# 48| 11: [ExprStmt] ...;
# 48| 0: [MethodCall] call to method GenericFn
# 48| -1: [ThisAccess] this access
# 48| 0: [IntLiteral] 2
# 51| 12: [ExprStmt] ...;
# 51| 0: [ObjectCreation] object creation of type C1
# 52| 13: [ExprStmt] ...;
# 52| 0: [ObjectCreation] object creation of type C1
# 52| 0: [IntLiteral] 1
# 53| 14: [ExprStmt] ...;
# 53| 0: [ObjectCreation] object creation of type C1
# 53| 0: [IntLiteral] 1
# 53| 1: [IntLiteral] 2
# 56| 15: [LocalVariableDeclStmt] ... ...;
# 56| 0: [LocalVariableDeclAndInitExpr] Int32 x = ...
# 56| 0: [IntLiteral] 2
# 56| 1: [LocalVariableAccess] access to local variable x
# 56| 1: [LocalVariableDeclAndInitExpr] Int32 y = ...
# 56| 0: [LocalVariableAccess] access to local variable x
# 56| 1: [LocalVariableAccess] access to local variable y
# 56| 2: [LocalVariableDeclAndInitExpr] Int32 z = ...
# 56| 0: [FieldAccess] access to field field1
# 56| 1: [LocalVariableAccess] access to local variable z
# 56| 3: [LocalVariableDeclAndInitExpr] Int32 w = ...
# 56| 0: [ArrayAccess] access to array element
# 56| -1: [ParameterAccess] access to parameter args
# 56| 0: [IntLiteral] 0
# 56| 1: [LocalVariableAccess] access to local variable w
# 57| 16: [LocalVariableDeclStmt] ... ...;
# 57| 0: [LocalVariableDeclAndInitExpr] Enumeration e = ...
# 57| 0: [MemberConstantAccess] access to constant e1
# 57| -1: [TypeAccess] access to type Enumeration
# 57| 1: [LocalVariableAccess] access to local variable e
# 60| 17: [ExprStmt] ...;
# 60| 0: [AssignExpr] ... = ...
# 60| 0: [AddExpr] ... + ...
# 60| 0: [PropertyCall] access to property property1
# 60| 1: [IntLiteral] 1
# 60| 1: [PropertyCall] access to property property1
# 63| 18: [LocalVariableDeclStmt] ... ...;
# 63| 0: [LocalVariableDeclAndInitExpr] C1[] array = ...
# 63| 0: [NullLiteral] null
# 63| 1: [LocalVariableAccess] access to local variable array
# 64| 19: [LocalVariableDeclStmt] ... ...;
# 64| 0: [LocalVariableDeclAndInitExpr] Nullable<S1> nullable = ...
# 64| 0: [NullLiteral] null
# 64| 1: [LocalVariableAccess] access to local variable nullable
# 67| 20: [LocalVariableDeclStmt] ... ...;
# 67| 0: [LocalVariableDeclAndInitExpr] Action<Int32> m1 = ...
# 67| 0: [ImplicitDelegateCreation] delegate creation of type Action<Int32>
# 67| 0: [MethodAccess] access to method GenericFn
# 67| 1: [LocalVariableAccess] access to local variable m1
# 70| 8: [Method] VariableTypeUse
#-----| 2: (Parameters)
# 70| 0: [Parameter] c1
# 71| 4: [BlockStmt] {...}
# 72| 0: [LocalVariableDeclStmt] ... ...;
# 72| 0: [LocalVariableDeclAndInitExpr] C1 c2 = ...
# 72| 0: [NullLiteral] null
# 72| 1: [LocalVariableAccess] access to local variable c2
# 75| 9: [Method] GenericFn
#-----| 1: (Type parameters)
# 75| 0: [TypeParameter] T
#-----| 2: (Parameters)
# 75| 0: [Parameter] t
# 75| 4: [BlockStmt] {...}
# 78| 4: [Struct] S1
# 80| 5: [Method] M
#-----| 2: (Parameters)
# 80| 0: [Parameter] ss
# 81| 4: [BlockStmt] {...}
# 82| 0: [TryStmt] try {...} ...
# 83| 0: [BlockStmt] {...}
# 84| 0: [LocalVariableDeclStmt] ... ...;
# 84| 0: [LocalVariableDeclAndInitExpr] String timestamp = ...
# 84| 0: [MethodCall] call to method ToString
# 84| -1: [PropertyCall] access to property Now
# 84| -1: [TypeAccess] access to type DateTime
# 84| 0: [StringLiteral] "HH:mm:ss"
# 84| 1: [LocalVariableAccess] access to local variable timestamp
# 86| 1: [SpecificCatchClause] catch (...) {...}
# 86| 0: [LocalVariableDeclExpr] Exception e
# 87| 1: [BlockStmt] {...}
# 88| 0: [ForeachStmt] foreach (... ... in ...) ...
# 88| 0: [LocalVariableDeclExpr] S1 s
# 88| 1: [ParameterAccess] access to parameter ss
# 89| 2: [BlockStmt] {...}
# 92| 1: [LocalVariableDeclStmt] ... ...;
# 92| 0: [LocalVariableDeclAndInitExpr] Type temp = ...
# 92| 0: [TypeofExpr] typeof(...)
# 92| 0: [TypeAccess] access to type S1[]
# 92| 1: [LocalVariableAccess] access to local variable temp
# 93| 2: [ReturnStmt] return ...;
# 93| 0: [ObjectCreation] object creation of type S1
# 97| 5: [Class] A
# 99| 5: [DelegateType] EventHandler
# 101| 6: [Event] Click
# 101| 3: [RemoveEventAccessor] remove_Click
#-----| 2: (Parameters)
# 101| 0: [Parameter] value
# 101| 3: [AddEventAccessor] add_Click
#-----| 2: (Parameters)
# 101| 0: [Parameter] value
# 103| 7: [Method] M
# 104| 4: [BlockStmt] {...}
# 105| 0: [ExprStmt] ...;
# 105| 0: [AddEventExpr] ... += ...
# 105| 0: [ImplicitDelegateCreation] delegate creation of type EventHandler
# 105| 0: [MethodAccess] access to method M
# 105| 1: [EventAccess,EventCall] access to event Click
# 106| 1: [LocalFunctionStmt] LocalFunction(...)
# 106| 0: [LocalFunction] LocalFunction
# 106| 4: [BlockStmt] {...}
# 106| 2: [EmptyStmt] ;
# 107| 3: [ExprStmt] ...;
# 107| 0: [AddEventExpr] ... += ...
# 107| 0: [ImplicitDelegateCreation] delegate creation of type EventHandler
# 107| 0: [LocalFunctionAccess] access to local function LocalFunction
# 107| 1: [EventAccess,EventCall] access to event Click
# 108| 4: [ExprStmt] ...;
# 108| 0: [DelegateCall] delegate call
# 108| -1: [EventAccess,EventCall] access to event Click
# 112| 6: [Interface] I1
# 114| 4: [Method] M2
#-----| 1: (Type parameters)
# 114| 0: [TypeParameter] T
# 117| 7: [Interface] I2<>
#-----| 1: (Type parameters)
# 117| 0: [TypeParameter] T
# 119| 8: [Interface] I3
#-----| 3: (Base types)
# 119| 1: [Interface] I2<Object>
# 121| 9: [Class] B<>
#-----| 1: (Type parameters)
# 121| 0: [TypeParameter] T
#-----| 3: (Base types)
# 121| 0: [Class] A
# 121| 1: [Interface] I1
# 121| 2: [Interface] I2<A>
# 123| 5: [Method] M
# 124| 4: [BlockStmt] {...}
# 125| 0: [ExprStmt] ...;
# 125| 0: [MethodCall] call to method M
# 125| -1: [BaseAccess] base access
# 128| 6: [Method] M2
#-----| 1: (Type parameters)
# 128| 0: [TypeParameter] T
# 128| 4: [BlockStmt] {...}
# 130| 7: [Struct] S<>
#-----| 1: (Type parameters)
# 130| 0: [TypeParameter] T2
#-----| 3: (Base types)
# 130| 1: [Interface] I3
# 132| 8: [Method] Tuple
# 132| 4: [ThrowExpr] throw ...
# 132| 0: [ObjectCreation] object creation of type Exception
# 134| 9: [Indexer] Item
#-----| 1: (Parameters)
# 134| 0: [Parameter] a
# 134| 3: [Getter] get_Item
#-----| 2: (Parameters)
# 134| 0: [Parameter] a
# 134| 4: [BlockStmt] {...}
# 134| 0: [ReturnStmt] return ...;
# 134| 0: [DefaultValueExpr] default(...)
# 134| 0: [TypeAccess] access to type B<A>
# 137| 10: [Class] C
# 139| 5: [Enum] E
# 140| 6: [Method] Pointer
# 140| 4: [ThrowExpr] throw ...
# 140| 0: [ObjectCreation] object creation of type Exception
# 140| 0: [MethodCall] call to method ToString
# 140| -1: [SizeofExpr] sizeof(..)
# 140| 0: [TypeAccess] access to type E*
# 143| 11: [Interface] I4
# 145| 4: [Event] EH
# 145| 3: [RemoveEventAccessor] remove_EH
#-----| 2: (Parameters)
# 145| 0: [Parameter] value
# 145| 3: [AddEventAccessor] add_EH
#-----| 2: (Parameters)
# 145| 0: [Parameter] value
# 146| 5: [Method] M
# 147| 6: [Property] P
# 147| 3: [Getter] get_P
# 148| 7: [Indexer] Item
#-----| 1: (Parameters)
# 148| 0: [Parameter] eh
# 148| 3: [Getter] get_Item
#-----| 2: (Parameters)
# 148| 0: [Parameter] eh
# 151| 12: [Class] C4
#-----| 3: (Base types)
# 151| 1: [Interface] I4
# 153| 5: [Event] EH
# 153| 3: [AddEventAccessor] add_EH
#-----| 2: (Parameters)
# 153| 0: [Parameter] value
# 153| 4: [BlockStmt] {...}
# 153| 4: [RemoveEventAccessor] remove_EH
#-----| 2: (Parameters)
# 153| 0: [Parameter] value
# 153| 4: [BlockStmt] {...}
# 154| 6: [Method] M
# 154| 4: [ThrowExpr] throw ...
# 154| 0: [ObjectCreation] object creation of type Exception
# 155| 7: [Property] P
# 155| 3: [Getter] get_P
# 155| 4: [ThrowExpr] throw ...
# 155| 0: [ObjectCreation] object creation of type Exception
# 156| 8: [Indexer] Item
#-----| 1: (Parameters)
# 156| 0: [Parameter] eh
# 156| 3: [Getter] get_Item
#-----| 2: (Parameters)
# 156| 0: [Parameter] eh
# 156| 4: [BlockStmt] {...}
# 156| 0: [ReturnStmt] return ...;
# 156| 0: [CastExpr] (...) ...
# 156| 0: [ObjectCreation] object creation of type S1
# 156| 1: [TypeAccess] access to type S1
# 158| 9: [Class] Nested<>
#-----| 1: (Type parameters)
# 158| 0: [TypeParameter] T
# 160| 5: [Method] Create
# 160| 4: [BlockStmt] {...}
# 160| 0: [ReturnStmt] return ...;
# 160| 0: [ObjectCreation] object creation of type Nested<>
# 164| 13: [Class] C5
# 166| 5: [Field] f
# 166| 1: [AssignExpr] ... = ...
# 166| 0: [MethodCall] call to method Create
# 166| -1: [TypeAccess] access to type Nested<I4>
# 166| -1: [TypeAccess] access to type C4
# 166| 1: [FieldAccess] access to field f
# 167| 6: [Field] c1
# 169| 7: [Method] M
# 170| 4: [BlockStmt] {...}
# 171| 0: [LocalVariableDeclStmt] ... ...;
# 171| 0: [LocalVariableDeclAndInitExpr] C1 c = ...
# 171| 0: [ObjectCreation] object creation of type C1
# 171| 1: [LocalVariableAccess] access to local variable c
# 172| 1: [ExprStmt] ...;
# 172| 0: [AssignExpr] ... = ...
# 172| 0: [PropertyCall] access to property property1
# 172| -1: [LocalVariableAccess] access to local variable c
# 172| 1: [PropertyCall] access to property property1
# 172| -1: [LocalVariableAccess] access to local variable c
# 173| 2: [LocalVariableDeclStmt] ... ...;
# 173| 0: [LocalVariableDeclAndInitExpr] C5 c5 = ...
# 173| 0: [AsExpr] ... as ...
# 173| 0: [ObjectCreation] object creation of type C5
# 173| 1: [TypeAccess] access to type C5
# 173| 1: [LocalVariableAccess] access to local variable c5
# 174| 3: [ExprStmt] ...;
# 174| 0: [AssignExpr] ... = ...
# 174| 0: [IntLiteral] 0
# 174| 1: [PropertyCall] access to property property1
# 174| -1: [FieldAccess] access to field c1
# 174| -1: [LocalVariableAccess] access to local variable c5
# 175| 4: [LocalVariableDeclStmt] ... ...;
# 175| 0: [LocalVariableDeclAndInitExpr] Boolean temp = ...
# 175| 0: [IsExpr] ... is ...
# 175| 0: [LocalVariableAccess] access to local variable c5
# 175| 1: [TypeAccessPatternExpr] access to type Nested<I4>
# 175| 1: [LocalVariableAccess] access to local variable temp
# 179| 14: [Class] C6
# 181| 5: [ExplicitConversionOperator] explicit conversion
#-----| 2: (Parameters)
# 181| 0: [Parameter] c
#-----| 0: (Attributes)
# 181| 1: [Attribute] [My(...)]
# 182| 4: [BlockStmt] {...}
# 183| 0: [ReturnStmt] return ...;
# 183| 0: [NullLiteral] null
# 186| 6: [Method] M
# 187| 4: [BlockStmt] {...}
# 188| 0: [ReturnStmt] return ...;
# 188| 0: [OperatorCall] call to operator explicit conversion
# 188| 0: [ThisAccess] this access
# 191| 7: [AddOperator] +
#-----| 2: (Parameters)
# 191| 0: [Parameter] x
# 191| 1: [Parameter] y
# 191| 4: [ParameterAccess] access to parameter x
# 194| 15: [Class] MyAttribute
#-----| 3: (Base types)
# 194| 0: [Class] Attribute
# 196| 16: [Class] C7
# 198| 5: [Method] M
# 198| 4: [BlockStmt] {...}
# 200| 6: [Method] M2
# 201| 4: [BlockStmt] {...}
# 202| 0: [ExprStmt] ...;
# 202| 0: [MethodCall] call to method M
# 202| -1: [TypeAccess] access to type C7
# 206| 17: [Class] C8
# 208| 5: [Method] F
# 209| 4: [BlockStmt] {...}
# 210| 0: [LocalVariableDeclStmt] ... ...;
# 210| 0: [LocalVariableDeclAndInitExpr] C8 c8a = ...
# 210| 0: [NullLiteral] null
# 210| 1: [LocalVariableAccess] access to local variable c8a
# 211| 1: [IfStmt] if (...) ...
# 211| 0: [IsExpr] ... is ...
# 211| 0: [LocalVariableAccess] access to local variable c8a
# 211| 1: [VariablePatternExpr] C8 c8b
# 212| 1: [ExprStmt] ...;
# 212| 0: [AssignExpr] ... = ...
# 212| 0: [LocalVariableAccess] access to local variable c8b
# 212| 1: [LocalVariableAccess] access to local variable c8a
# 213| 2: [SwitchStmt] switch (...) {...}
# 213| 0: [LocalVariableAccess] access to local variable c8a
# 215| 0: [CaseStmt] case ...:
# 215| 0: [VariablePatternExpr] C8 c8c
# 215| 1: [NEExpr] ... != ...
# 215| 0: [LocalVariableAccess] access to local variable c8c
# 215| 1: [NullLiteral] null
# 216| 1: [ExprStmt] ...;
# 216| 0: [AssignExpr] ... = ...
# 216| 0: [LocalVariableAccess] access to local variable c8c
# 216| 1: [LocalVariableAccess] access to local variable c8a
# 217| 2: [BreakStmt] break;

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,190 @@
delegates.cs:
# 5| [NamespaceDeclaration] namespace ... { ... }
# 7| 1: [DelegateType] FooDelegate
#-----| 2: (Parameters)
# 7| 0: [Parameter] param
# 7| 1: [Parameter] condition
# 7| 2: [Parameter] args
# 9| 2: [DelegateType] D1
#-----| 2: (Parameters)
# 9| 0: [Parameter] i
# 9| 1: [Parameter] d
# 11| 3: [Class] A
# 14| 5: [Method] M1
#-----| 2: (Parameters)
# 14| 0: [Parameter] a
# 14| 1: [Parameter] b
# 14| 4: [BlockStmt] {...}
# 14| 0: [ReturnStmt] return ...;
# 14| 0: [CastExpr] (...) ...
# 14| 0: [AddExpr] ... + ...
# 14| 0: [CastExpr] (...) ...
# 14| 0: [ParameterAccess] access to parameter a
# 14| 1: [ParameterAccess] access to parameter b
# 14| 1: [TypeAccess] access to type Int32
# 18| 4: [Class] B
# 21| 5: [DelegateType] D2
#-----| 2: (Parameters)
# 21| 0: [Parameter] c
# 21| 1: [Parameter] d
# 23| 6: [Method] M1
#-----| 2: (Parameters)
# 23| 0: [Parameter] f
# 23| 1: [Parameter] g
# 23| 4: [BlockStmt] {...}
# 23| 0: [ReturnStmt] return ...;
# 23| 0: [SubExpr] ... - ...
# 23| 0: [ParameterAccess] access to parameter f
# 23| 1: [CastExpr] (...) ...
# 23| 0: [ParameterAccess] access to parameter g
# 23| 1: [TypeAccess] access to type Int32
# 25| 7: [Method] M2
#-----| 2: (Parameters)
# 25| 0: [Parameter] k
# 25| 1: [Parameter] l
# 25| 4: [BlockStmt] {...}
# 27| 8: [Method] M3
#-----| 2: (Parameters)
# 27| 0: [Parameter] g
# 27| 4: [BlockStmt] {...}
# 27| 0: [ReturnStmt] return ...;
# 27| 0: [AddExpr] ... + ...
# 27| 0: [UnaryMinusExpr] -...
# 27| 0: [ParameterAccess] access to parameter g
# 27| 1: [UnaryPlusExpr] +...
# 27| 0: [ParameterAccess] access to parameter g
# 29| 9: [Method] M4
#-----| 2: (Parameters)
# 29| 0: [Parameter] g
# 29| 4: [BlockStmt] {...}
# 33| 5: [DelegateType] Predicate<>
#-----| 1: (Type parameters)
# 33| 0: [TypeParameter] T
#-----| 2: (Parameters)
# 33| 0: [Parameter] value
# 35| 6: [Class] X
# 38| 5: [Method] F
#-----| 2: (Parameters)
# 38| 0: [Parameter] i
# 38| 4: [BlockStmt] {...}
# 38| 0: [ReturnStmt] return ...;
# 38| 0: [LTExpr] ... < ...
# 38| 0: [ParameterAccess] access to parameter i
# 38| 1: [IntLiteral] 2
# 40| 6: [Method] G
#-----| 2: (Parameters)
# 40| 0: [Parameter] s
# 40| 4: [BlockStmt] {...}
# 40| 0: [ReturnStmt] return ...;
# 40| 0: [BoolLiteral] false
# 44| 7: [DelegateType] D
#-----| 2: (Parameters)
# 44| 0: [Parameter] x
# 46| 8: [Class] C
# 49| 5: [Method] M1
#-----| 2: (Parameters)
# 49| 0: [Parameter] i
# 49| 4: [BlockStmt] {...}
# 50| 6: [Method] M2
#-----| 2: (Parameters)
# 50| 0: [Parameter] i
# 50| 4: [BlockStmt] {...}
# 51| 7: [Method] M3
#-----| 2: (Parameters)
# 51| 0: [Parameter] i
# 51| 4: [BlockStmt] {...}
# 55| 9: [Class] Test
# 58| 5: [Method] Main
# 59| 4: [BlockStmt] {...}
# 60| 0: [LocalVariableDeclStmt] ... ...;
# 60| 0: [LocalVariableDeclAndInitExpr] D cd1 = ...
# 60| 0: [ExplicitDelegateCreation] delegate creation of type D
# 60| 0: [MethodAccess] access to method M1
# 60| -1: [TypeAccess] access to type C
# 60| 1: [LocalVariableAccess] access to local variable cd1
# 61| 1: [LocalVariableDeclStmt] ... ...;
# 61| 0: [LocalVariableDeclAndInitExpr] D cd2 = ...
# 61| 0: [ImplicitDelegateCreation] delegate creation of type D
# 61| 0: [MethodAccess] access to method M2
# 61| -1: [TypeAccess] access to type C
# 61| 1: [LocalVariableAccess] access to local variable cd2
# 62| 2: [LocalVariableDeclStmt] ... ...;
# 62| 0: [LocalVariableDeclAndInitExpr] D cd3 = ...
# 62| 0: [OperatorCall] call to operator +
# 62| 0: [LocalVariableAccess] access to local variable cd1
# 62| 1: [LocalVariableAccess] access to local variable cd2
# 62| 1: [LocalVariableAccess] access to local variable cd3
# 63| 3: [LocalVariableDeclStmt] ... ...;
# 63| 0: [LocalVariableDeclAndInitExpr] D cd4 = ...
# 63| 0: [OperatorCall] call to operator +
# 63| 0: [LocalVariableAccess] access to local variable cd3
# 63| 1: [LocalVariableAccess] access to local variable cd1
# 63| 1: [LocalVariableAccess] access to local variable cd4
# 64| 4: [LocalVariableDeclStmt] ... ...;
# 64| 0: [LocalVariableDeclAndInitExpr] D cd5 = ...
# 64| 0: [OperatorCall] call to operator -
# 64| 0: [LocalVariableAccess] access to local variable cd4
# 64| 1: [LocalVariableAccess] access to local variable cd3
# 64| 1: [LocalVariableAccess] access to local variable cd5
# 65| 5: [ExprStmt] ...;
# 65| 0: [AssignAddExpr] ... += ...
# 65| 0: [LocalVariableAccess] access to local variable cd5
# 65| 1: [LocalVariableAccess] access to local variable cd4
# 66| 6: [ExprStmt] ...;
# 66| 0: [AssignSubExpr] ... -= ...
# 66| 0: [LocalVariableAccess] access to local variable cd1
# 66| 1: [LocalVariableAccess] access to local variable cd4
# 68| 7: [LocalVariableDeclStmt] ... ...;
# 68| 0: [LocalVariableDeclAndInitExpr] C c = ...
# 68| 0: [ObjectCreation] object creation of type C
# 68| 1: [LocalVariableAccess] access to local variable c
# 69| 8: [LocalVariableDeclStmt] ... ...;
# 69| 0: [LocalVariableDeclAndInitExpr] D cd6 = ...
# 69| 0: [ExplicitDelegateCreation] delegate creation of type D
# 69| 0: [MethodAccess] access to method M3
# 69| -1: [LocalVariableAccess] access to local variable c
# 69| 1: [LocalVariableAccess] access to local variable cd6
# 70| 9: [LocalVariableDeclStmt] ... ...;
# 70| 0: [LocalVariableDeclAndInitExpr] D cd7 = ...
# 70| 0: [ExplicitDelegateCreation] delegate creation of type D
# 70| 0: [LocalVariableAccess] access to local variable cd6
# 70| 1: [LocalVariableAccess] access to local variable cd7
# 72| 10: [ExprStmt] ...;
# 72| 0: [DelegateCall] delegate call
# 72| -1: [LocalVariableAccess] access to local variable cd1
# 72| 0: [UnaryMinusExpr] -...
# 72| 0: [IntLiteral] 40
# 73| 11: [LocalVariableDeclStmt] ... ...;
# 73| 0: [LocalVariableDeclAndInitExpr] Int32 x = ...
# 73| 0: [IntLiteral] 0
# 73| 1: [LocalVariableAccess] access to local variable x
# 74| 12: [ExprStmt] ...;
# 74| 0: [DelegateCall] delegate call
# 74| -1: [LocalVariableAccess] access to local variable cd7
# 74| 0: [AddExpr] ... + ...
# 74| 0: [IntLiteral] 34
# 74| 1: [LocalVariableAccess] access to local variable x
# 76| 13: [LocalVariableDeclStmt] ... ...;
# 76| 0: [LocalVariableDeclAndInitExpr] Predicate<Int32> pi = ...
# 76| 0: [ExplicitDelegateCreation] delegate creation of type Predicate<Int32>
# 76| 0: [MethodAccess] access to method F
# 76| -1: [TypeAccess] access to type X
# 76| 1: [LocalVariableAccess] access to local variable pi
# 77| 14: [LocalVariableDeclStmt] ... ...;
# 77| 0: [LocalVariableDeclAndInitExpr] Predicate<String> ps = ...
# 77| 0: [ImplicitDelegateCreation] delegate creation of type Predicate<String>
# 77| 0: [MethodAccess] access to method G
# 77| -1: [TypeAccess] access to type X
# 77| 1: [LocalVariableAccess] access to local variable ps
# 79| 15: [LocalVariableDeclStmt] ... ...;
# 79| 0: [LocalVariableDeclAndInitExpr] Boolean b = ...
# 79| 0: [BitwiseAndExpr] ... & ...
# 79| 0: [DelegateCall] delegate call
# 79| -1: [LocalVariableAccess] access to local variable pi
# 79| 0: [IntLiteral] 3
# 79| 1: [DelegateCall] delegate call
# 79| -1: [LocalVariableAccess] access to local variable ps
# 79| 0: [StringLiteral] ""
# 79| 1: [LocalVariableAccess] access to local variable b
# 81| 16: [LocalVariableDeclStmt] ... ...;
# 81| 0: [LocalVariableDeclExpr] ContextCallback d

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,252 @@
dynamic.cs:
# 4| [Class] DynamicTest
# 6| 4: [InstanceConstructor] DynamicTest
#-----| 2: (Parameters)
# 6| 0: [Parameter] x
# 6| 4: [BlockStmt] {...}
# 8| 5: [Method] Main
#-----| 2: (Parameters)
# 8| 0: [Parameter] args
# 9| 4: [BlockStmt] {...}
# 10| 0: [LocalVariableDeclStmt] ... ...;
# 10| 0: [LocalVariableDeclAndInitExpr] DynamicTest dt = ...
# 10| 0: [ObjectCreation] object creation of type DynamicTest
# 10| 0: [IntLiteral] 0
# 10| 1: [LocalVariableAccess] access to local variable dt
# 11| 1: [LocalVariableDeclStmt] ... ...;
# 11| 0: [LocalVariableDeclAndInitExpr] Int32[] array = ...
# 11| 0: [ArrayCreation] array creation of type Int32[]
# 11| -1: [ArrayInitializer] { ..., ... }
# 11| 0: [IntLiteral] 42
# 11| 1: [LocalVariableAccess] access to local variable array
# 12| 2: [LocalVariableDeclStmt] ... ...;
# 12| 0: [LocalVariableDeclAndInitExpr] Action<Int32> action = ...
# 12| 0: [LambdaExpr] (...) => ...
#-----| 2: (Parameters)
# 12| 0: [Parameter] x
# 12| 4: [BlockStmt] {...}
# 12| 1: [LocalVariableAccess] access to local variable action
# 13| 3: [LocalVariableDeclStmt] ... ...;
# 13| 0: [LocalVariableDeclAndInitExpr] dynamic d = ...
# 13| 0: [CastExpr] (...) ...
# 13| 0: [IntLiteral] 0
# 13| 1: [LocalVariableAccess] access to local variable d
# 16| 4: [ExprStmt] ...;
# 16| 0: [DynamicObjectCreation] dynamic object creation of type DynamicTest
# 16| 0: [LocalVariableAccess] access to local variable d
# 17| 5: [ExprStmt] ...;
# 17| 0: [DynamicObjectCreation] dynamic object creation of type DynamicTest
# 17| -1: [ObjectInitializer] { ..., ... }
# 17| 0: [MemberInitializer] ... = ...
# 17| 0: [CastExpr] (...) ...
# 17| 0: [LocalVariableAccess] access to local variable d
# 17| 1: [FieldAccess] access to field Field
# 17| 0: [LocalVariableAccess] access to local variable d
# 18| 6: [ExprStmt] ...;
# 18| 0: [DynamicObjectCreation] dynamic object creation of type KeyValuePair<String,dynamic>
# 18| 0: [StringLiteral] ""
# 18| 1: [LocalVariableAccess] access to local variable d
# 19| 7: [ExprStmt] ...;
# 19| 0: [DynamicObjectCreation] dynamic object creation of type KeyValuePair<String,dynamic>
# 19| 0: [StringLiteral] ""
# 19| 1: [LocalVariableAccess] access to local variable d
# 22| 8: [ExprStmt] ...;
# 22| 0: [ObjectCreation] object creation of type DynamicTest
# 22| 0: [IntLiteral] 0
# 23| 9: [ExprStmt] ...;
# 23| 0: [ObjectCreation] object creation of type DynamicTest
# 23| -1: [ObjectInitializer] { ..., ... }
# 23| 0: [MemberInitializer] ... = ...
# 23| 0: [CastExpr] (...) ...
# 23| 0: [LocalVariableAccess] access to local variable d
# 23| 1: [FieldAccess] access to field Field
# 23| 0: [IntLiteral] 0
# 26| 10: [ExprStmt] ...;
# 26| 0: [DynamicMethodCall] dynamic call to method Bar
# 26| -1: [LocalVariableAccess] access to local variable d
# 26| 0: [StringLiteral] ""
# 27| 11: [ExprStmt] ...;
# 27| 0: [DynamicMethodCall] dynamic call to method Foo
# 27| 0: [LocalVariableAccess] access to local variable d
# 30| 12: [ExprStmt] ...;
# 30| 0: [MethodCall] call to method Bar
# 30| -1: [LocalVariableAccess] access to local variable dt
# 30| 0: [StringLiteral] ""
# 31| 13: [ExprStmt] ...;
# 31| 0: [MethodCall] call to method Foo
# 31| 0: [IntLiteral] 0
# 34| 14: [ExprStmt] ...;
# 34| 0: [AssignExpr] ... = ...
# 34| 0: [CastExpr] (...) ...
# 34| 0: [IntLiteral] 0
# 34| 1: [LocalVariableAccess] access to local variable d
# 35| 15: [ExprStmt] ...;
# 35| 0: [AssignExpr] ... = ...
# 35| 0: [DynamicOperatorCall] dynamic call to operator -
# 35| 0: [LocalVariableAccess] access to local variable d
# 35| 1: [LocalVariableAccess] access to local variable d
# 36| 16: [ExprStmt] ...;
# 36| 0: [AssignExpr] ... = ...
# 36| 0: [DynamicOperatorCall] dynamic call to operator +
# 36| 0: [LocalVariableAccess] access to local variable d
# 36| 1: [LocalVariableAccess] access to local variable d
# 36| 1: [LocalVariableAccess] access to local variable d
# 37| 17: [ExprStmt] ...;
# 37| 0: [AssignAddExpr] ... += ...
# 37| 0: [LocalVariableAccess] access to local variable d
# 37| 1: [LocalVariableAccess] access to local variable d
# 40| 18: [LocalVariableDeclStmt] ... ...;
# 40| 0: [LocalVariableDeclAndInitExpr] Int32 i = ...
# 40| 0: [IntLiteral] 0
# 40| 1: [LocalVariableAccess] access to local variable i
# 41| 19: [ExprStmt] ...;
# 41| 0: [AssignExpr] ... = ...
# 41| 0: [UnaryMinusExpr] -...
# 41| 0: [LocalVariableAccess] access to local variable i
# 41| 1: [LocalVariableAccess] access to local variable i
# 42| 20: [ExprStmt] ...;
# 42| 0: [AssignExpr] ... = ...
# 42| 0: [AddExpr] ... + ...
# 42| 0: [LocalVariableAccess] access to local variable i
# 42| 1: [LocalVariableAccess] access to local variable i
# 42| 1: [LocalVariableAccess] access to local variable i
# 43| 21: [ExprStmt] ...;
# 43| 0: [AssignAddExpr] ... += ...
# 43| 0: [LocalVariableAccess] access to local variable i
# 43| 1: [LocalVariableAccess] access to local variable i
# 44| 22: [ExprStmt] ...;
# 44| 0: [PostIncrExpr] ...++
# 44| 0: [LocalVariableAccess] access to local variable i
# 47| 23: [ExprStmt] ...;
# 47| 0: [DynamicOperatorCall] dynamic call to operator ++
# 47| 0: [LocalVariableAccess] access to local variable d
# 50| 24: [ExprStmt] ...;
# 50| 0: [PostIncrExpr] ...++
# 50| 0: [LocalVariableAccess] access to local variable i
# 53| 25: [ExprStmt] ...;
# 53| 0: [AssignExpr] ... = ...
# 53| 0: [IntLiteral] 0
# 53| 1: [DynamicMemberAccess] dynamic access to member Field
# 53| -1: [LocalVariableAccess] access to local variable d
# 54| 26: [ExprStmt] ...;
# 54| 0: [AssignExpr] ... = ...
# 54| 0: [DynamicMemberAccess] dynamic access to member Prop
# 54| -1: [LocalVariableAccess] access to local variable d
# 54| 1: [DynamicMemberAccess] dynamic access to member Prop
# 54| -1: [LocalVariableAccess] access to local variable d
# 57| 27: [ExprStmt] ...;
# 57| 0: [AssignExpr] ... = ...
# 57| 0: [IntLiteral] 0
# 57| 1: [FieldAccess] access to field Field
# 57| -1: [LocalVariableAccess] access to local variable dt
# 58| 28: [ExprStmt] ...;
# 58| 0: [AssignExpr] ... = ...
# 58| 0: [PropertyCall] access to property Prop
# 58| -1: [LocalVariableAccess] access to local variable dt
# 58| 1: [PropertyCall] access to property Prop
# 58| -1: [LocalVariableAccess] access to local variable dt
# 61| 29: [ExprStmt] ...;
# 61| 0: [AssignExpr] ... = ...
# 61| 0: [LocalVariableAccess] access to local variable array
# 61| 1: [LocalVariableAccess] access to local variable d
# 62| 30: [ExprStmt] ...;
# 62| 0: [AssignExpr] ... = ...
# 62| 0: [DynamicElementAccess] dynamic access to element
# 62| -1: [LocalVariableAccess] access to local variable d
# 62| 0: [IntLiteral] 0
# 62| 1: [DynamicElementAccess] dynamic access to element
# 62| -1: [LocalVariableAccess] access to local variable d
# 62| 0: [IntLiteral] 0
# 63| 31: [ExprStmt] ...;
# 63| 0: [AssignExpr] ... = ...
# 63| 0: [DynamicElementAccess] dynamic access to element
# 63| -1: [LocalVariableAccess] access to local variable d
# 63| 0: [IntLiteral] 0
# 63| 1: [LocalVariableAccess] access to local variable d
# 66| 32: [ExprStmt] ...;
# 66| 0: [AssignExpr] ... = ...
# 66| 0: [CastExpr] (...) ...
# 66| 0: [IntLiteral] 0
# 66| 1: [LocalVariableAccess] access to local variable d
# 67| 33: [ExprStmt] ...;
# 67| 0: [AssignExpr] ... = ...
# 67| 0: [CastExpr] (...) ...
# 67| 0: [IndexerCall] access to indexer
# 67| -1: [LocalVariableAccess] access to local variable dt
# 67| 0: [LocalVariableAccess] access to local variable d
# 67| 1: [IndexerCall] access to indexer
# 67| -1: [LocalVariableAccess] access to local variable dt
# 67| 0: [IntLiteral] 0
# 68| 34: [ExprStmt] ...;
# 68| 0: [AssignExpr] ... = ...
# 68| 0: [CastExpr] (...) ...
# 68| 0: [IndexerCall] access to indexer
# 68| -1: [LocalVariableAccess] access to local variable dt
# 68| 0: [IntLiteral] 0
# 68| 1: [LocalVariableAccess] access to local variable d
# 69| 35: [ExprStmt] ...;
# 69| 0: [AssignExpr] ... = ...
# 69| 0: [ArrayAccess] access to array element
# 69| -1: [LocalVariableAccess] access to local variable array
# 69| 0: [CastExpr] (...) ...
# 69| 0: [LocalVariableAccess] access to local variable d
# 69| 1: [ArrayAccess] access to array element
# 69| -1: [LocalVariableAccess] access to local variable array
# 69| 0: [IntLiteral] 0
# 70| 36: [ExprStmt] ...;
# 70| 0: [AssignExpr] ... = ...
# 70| 0: [CastExpr] (...) ...
# 70| 0: [ArrayAccess] access to array element
# 70| -1: [LocalVariableAccess] access to local variable array
# 70| 0: [IntLiteral] 0
# 70| 1: [LocalVariableAccess] access to local variable d
# 73| 37: [ExprStmt] ...;
# 73| 0: [DelegateCall] delegate call
# 73| -1: [LocalVariableAccess] access to local variable action
# 73| 0: [IntLiteral] 3
# 74| 38: [ExprStmt] ...;
# 74| 0: [AssignExpr] ... = ...
# 74| 0: [LocalVariableAccess] access to local variable action
# 74| 1: [LocalVariableAccess] access to local variable d
# 75| 39: [ExprStmt] ...;
# 75| 0: [DelegateCall] delegate call
# 75| -1: [LocalVariableAccess] access to local variable d
# 75| 0: [IntLiteral] 42
# 78| 6: [Method] Foo
#-----| 2: (Parameters)
# 78| 0: [Parameter] x
# 78| 4: [BlockStmt] {...}
# 79| 7: [Method] Foo
#-----| 2: (Parameters)
# 79| 0: [Parameter] x
# 79| 4: [BlockStmt] {...}
# 81| 8: [Method] Bar
#-----| 2: (Parameters)
# 81| 0: [Parameter] x
# 81| 4: [BlockStmt] {...}
# 83| 9: [IncrementOperator] ++
#-----| 2: (Parameters)
# 83| 0: [Parameter] dt
# 84| 4: [BlockStmt] {...}
# 85| 0: [ReturnStmt] return ...;
# 85| 0: [ParameterAccess] access to parameter dt
# 88| 10: [Field] Field
# 90| 11: [Property] Prop
# 90| 3: [Getter] get_Prop
# 90| 4: [Setter] set_Prop
#-----| 2: (Parameters)
# 90| 0: [Parameter] value
# 92| 12: [Indexer] Item
#-----| 1: (Parameters)
# 92| 0: [Parameter] x
# 92| 3: [Getter] get_Item
#-----| 2: (Parameters)
# 92| 0: [Parameter] x
# 92| 4: [BlockStmt] {...}
# 92| 0: [ReturnStmt] return ...;
# 92| 0: [ParameterAccess] access to parameter x
# 92| 4: [Setter] set_Item
#-----| 2: (Parameters)
# 92| 0: [Parameter] x
# 92| 1: [Parameter] value
# 92| 4: [BlockStmt] {...}

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

View File

@@ -0,0 +1,88 @@
enums.cs:
# 5| [NamespaceDeclaration] namespace ... { ... }
# 7| 1: [Enum] Color
# 10| 5: [Field] Red
# 10| 6: [Field] Green
# 10| 7: [Field] Blue
# 14| 2: [Enum] LongColor
# 17| 5: [Field] Red
# 18| 6: [Field] Green
# 19| 7: [Field] Blue
# 23| 3: [Enum] E
# 25| 4: [Enum] ValueColor
# 28| 5: [Field] OneRed
# 28| 1: [MemberConstantAccess] access to constant OneRed
# 29| 6: [Field] TwoGreen
# 29| 1: [MemberConstantAccess] access to constant TwoGreen
# 30| 7: [Field] FourBlue
# 30| 1: [MemberConstantAccess] access to constant FourBlue
# 34| 5: [Enum] SparseColor
# 37| 5: [Field] Red
# 38| 6: [Field] Green
# 38| 1: [MemberConstantAccess] access to constant Green
# 39| 7: [Field] Blue
# 40| 8: [Field] AnotherBlue
# 40| 1: [MemberConstantAccess] access to constant AnotherBlue
# 44| 6: [Class] Test
# 47| 5: [Method] Main
# 48| 4: [BlockStmt] {...}
# 49| 0: [ExprStmt] ...;
# 49| 0: [MethodCall] call to method WriteLine
# 49| -1: [TypeAccess] access to type Console
# 49| 0: [MethodCall] call to method StringFromColor
# 49| 0: [MemberConstantAccess] access to constant Red
# 49| -1: [TypeAccess] access to type SparseColor
# 50| 1: [ExprStmt] ...;
# 50| 0: [MethodCall] call to method WriteLine
# 50| -1: [TypeAccess] access to type Console
# 50| 0: [MethodCall] call to method StringFromColor
# 50| 0: [MemberConstantAccess] access to constant Green
# 50| -1: [TypeAccess] access to type SparseColor
# 51| 2: [ExprStmt] ...;
# 51| 0: [MethodCall] call to method WriteLine
# 51| -1: [TypeAccess] access to type Console
# 51| 0: [MethodCall] call to method StringFromColor
# 51| 0: [MemberConstantAccess] access to constant Blue
# 51| -1: [TypeAccess] access to type SparseColor
# 54| 6: [Method] StringFromColor
#-----| 2: (Parameters)
# 54| 0: [Parameter] c
# 55| 4: [BlockStmt] {...}
# 56| 0: [SwitchStmt] switch (...) {...}
# 56| 0: [ParameterAccess] access to parameter c
# 58| 0: [ConstCase] case ...:
# 58| 0: [ConstantPatternExpr,MemberConstantAccess] access to constant Red
# 58| -1: [TypeAccess] access to type SparseColor
# 58| 1: [ReturnStmt] return ...;
# 58| 0: [MethodCall] call to method Format
# 58| -1: [TypeAccess] access to type String
# 58| 0: [StringLiteral] "Red = {0}"
# 58| 1: [CastExpr] (...) ...
# 58| 0: [CastExpr] (...) ...
# 58| 0: [ParameterAccess] access to parameter c
# 58| 1: [TypeAccess] access to type Int32
# 59| 2: [ConstCase] case ...:
# 59| 0: [ConstantPatternExpr,MemberConstantAccess] access to constant Green
# 59| -1: [TypeAccess] access to type SparseColor
# 59| 3: [ReturnStmt] return ...;
# 59| 0: [MethodCall] call to method Format
# 59| -1: [TypeAccess] access to type String
# 59| 0: [StringLiteral] "Green = {0}"
# 59| 1: [CastExpr] (...) ...
# 59| 0: [CastExpr] (...) ...
# 59| 0: [ParameterAccess] access to parameter c
# 59| 1: [TypeAccess] access to type Int32
# 60| 4: [ConstCase] case ...:
# 60| 0: [ConstantPatternExpr,MemberConstantAccess] access to constant Blue
# 60| -1: [TypeAccess] access to type SparseColor
# 60| 5: [ReturnStmt] return ...;
# 60| 0: [MethodCall] call to method Format
# 60| -1: [TypeAccess] access to type String
# 60| 0: [StringLiteral] "Blue = {0}"
# 60| 1: [CastExpr] (...) ...
# 60| 0: [CastExpr] (...) ...
# 60| 0: [ParameterAccess] access to parameter c
# 60| 1: [TypeAccess] access to type Int32
# 61| 6: [DefaultCase] default:
# 61| 7: [ReturnStmt] return ...;
# 61| 0: [StringLiteral] "Invalid color"

View File

@@ -0,0 +1 @@
semmle/code/csharp/PrintAst.ql

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