diff --git a/change-notes/1.26/analysis-cpp.md b/change-notes/1.26/analysis-cpp.md index 083229e18c4..c37f9929eae 100644 --- a/change-notes/1.26/analysis-cpp.md +++ b/change-notes/1.26/analysis-cpp.md @@ -14,6 +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 many more taint flows through `std::string`. +* The `SimpleRangeAnalysis` library now supports multiplications of the form + `e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant. diff --git a/change-notes/1.26/analysis-csharp.md b/change-notes/1.26/analysis-csharp.md new file mode 100644 index 00000000000..5580938dc2a --- /dev/null +++ b/change-notes/1.26/analysis-csharp.md @@ -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. diff --git a/change-notes/1.26/analysis-javascript.md b/change-notes/1.26/analysis-javascript.md index 2615bb804d8..3c1f05c4fbb 100644 --- a/change-notes/1.26/analysis-javascript.md +++ b/change-notes/1.26/analysis-javascript.md @@ -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** | @@ -24,7 +26,7 @@ | **Query** | **Expected impact** | **Change** | |--------------------------------|------------------------------|---------------------------------------------------------------------------| +| Incomplete URL substring sanitization (`js/incomplete-url-substring-sanitization`) | More results | This query now recognizes additional URLs when the substring check is an inclusion check. | ## Changes to libraries - diff --git a/cpp/ql/src/Metrics/Files/FNumberOfTests.ql b/cpp/ql/src/Metrics/Files/FNumberOfTests.ql index a474b986203..421fc2baba1 100644 --- a/cpp/ql/src/Metrics/Files/FNumberOfTests.ql +++ b/cpp/ql/src/Metrics/Files/FNumberOfTests.ql @@ -18,6 +18,9 @@ Expr getTest() { or // boost tests; http://www.boost.org/ result.(FunctionCall).getTarget().hasQualifiedName("boost::unit_test", "make_test_case") + or + // googletest tests; https://github.com/google/googletest/ + result.(FunctionCall).getTarget().hasQualifiedName("testing::internal", "MakeAndRegisterTestInfo") } from File f, int n diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index 04ea9a9c5fa..b5185b3c908 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -1,5 +1,13 @@ +/** + * Provides classes for identifying and reasoning about Microsoft source code + * annotation language (SAL) macros. + */ + import cpp +/** + * A SAL macro defined in `sal.h` or a similar header file. + */ class SALMacro extends Macro { SALMacro() { exists(string filename | filename = this.getFile().getBaseName() | @@ -20,27 +28,34 @@ class SALMacro extends Macro { } pragma[noinline] -predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) } +private predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) } +/** + * An invocation of a SAL macro (excluding invocations inside other macros). + */ class SALAnnotation extends MacroInvocation { SALAnnotation() { this.getMacro() instanceof SALMacro and isTopLevelMacroAccess(this) } - /** Returns the `Declaration` annotated by `this`. */ + /** Gets the `Declaration` annotated by `this`. */ Declaration getDeclaration() { annotatesAt(this, result.getADeclarationEntry(), _, _) and not result instanceof Type // exclude typedefs } - /** Returns the `DeclarationEntry` annotated by `this`. */ + /** Gets the `DeclarationEntry` annotated by `this`. */ DeclarationEntry getDeclarationEntry() { annotatesAt(this, result, _, _) and not result instanceof TypeDeclarationEntry // exclude typedefs } } +/** + * A SAL macro indicating that the return value of a function should always be + * checked. + */ class SALCheckReturn extends SALAnnotation { SALCheckReturn() { exists(SALMacro m | m = this.getMacro() | @@ -50,6 +65,10 @@ class SALCheckReturn extends SALAnnotation { } } +/** + * A SAL macro indicating that a pointer variable or return value should not be + * `NULL`. + */ class SALNotNull extends SALAnnotation { SALNotNull() { exists(SALMacro m | m = this.getMacro() | @@ -69,6 +88,9 @@ class SALNotNull extends SALAnnotation { } } +/** + * A SAL macro indicating that a value may be `NULL`. + */ class SALMaybeNull extends SALAnnotation { SALMaybeNull() { exists(SALMacro m | m = this.getMacro() | @@ -79,13 +101,29 @@ class SALMaybeNull extends SALAnnotation { } } +/** + * A parameter annotated by one or more SAL annotations. + */ +class SALParameter extends Parameter { + /** One of this parameter's annotations. */ + SALAnnotation a; + + SALParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) } + + predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") } + + predicate isOut() { a.getMacroName().toLowerCase().matches("%\\_out%") } + + predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") } +} + /////////////////////////////////////////////////////////////////////////////// // Implementation details /** * Holds if `a` annotates the declaration entry `d` and * its start position is the `idx`th position in `file` that holds a SAL element. */ -predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, int idx) { +private predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, int idx) { annotatesAtPosition(a.(SALElement).getStartPosition(), d, file, idx) } @@ -109,22 +147,6 @@ private predicate annotatesAtPosition(SALPosition pos, DeclarationEntry d, File ) } -/** - * A parameter annotated by one or more SAL annotations. - */ -class SALParameter extends Parameter { - /** One of this parameter's annotations. */ - SALAnnotation a; - - SALParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) } - - predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") } - - predicate isOut() { a.getMacroName().toLowerCase().matches("%\\_out%") } - - predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") } -} - /** * A SAL element, that is, a SAL annotation or a declaration entry * that may have SAL annotations. diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 54c6d1e7a96..cc2d52385c7 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -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 diff --git a/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll new file mode 100644 index 00000000000..c8c1110b3af --- /dev/null +++ b/cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisExpr.qll @@ -0,0 +1,78 @@ +/** + * EXPERIMENTAL: The API of this module may change without notice. + * + * Provides a class for modeling `Expr`s with a restricted range. + */ + +import cpp +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis + +/** + * EXPERIMENTAL: The API of this class may change without notice. + * + * An expression for which a range can be deduced. Extend this class to add + * functionality to the range analysis library. + */ +abstract class SimpleRangeAnalysisExpr extends Expr { + /** + * Gets the lower bound of the expression. + * + * Implementations of this predicate should use + * `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for + * recursive calls to get the bounds of their children. + */ + abstract float getLowerBounds(); + + /** + * Gets the upper bound of the expression. + * + * Implementations of this predicate should use + * `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for + * recursive calls to get the bounds of their children. + */ + abstract float getUpperBounds(); + + /** + * Holds if the range this expression depends on the definition `srcDef` for + * StackVariable `srcVar`. + * + * Because this predicate cannot be recursive, most implementations should + * override `dependsOnChild` instead. + */ + predicate dependsOnDef(RangeSsaDefinition srcDef, StackVariable srcVar) { none() } + + /** + * Holds if this expression depends on the range of its unconverted + * subexpression `child`. This information is used to inform the range + * analysis about cyclic dependencies. Without this information, range + * analysis might work for simple cases but will go into infinite loops on + * complex code. + * + * For example, when modeling a function call whose return value depends on + * all of its arguments, implement this predicate as + * `child = this.getAnArgument()`. + */ + abstract predicate dependsOnChild(Expr child); +} + +import SimpleRangeAnalysisInternal + +/** + * This class exists to prevent the QL front end from emitting compile errors + * inside `SimpleRangeAnalysis.qll` about certain conjuncts being empty + * because the overrides of `SimpleRangeAnalysisExpr` that happen to be in + * scope do not make use of every feature it offers. + */ +private class Empty extends SimpleRangeAnalysisExpr { + Empty() { + // This predicate is complicated enough that the QL type checker doesn't + // see it as empty but simple enough that the optimizer should. + this = this and none() + } + + override float getLowerBounds() { none() } + + override float getUpperBounds() { none() } + + override predicate dependsOnChild(Expr child) { none() } +} diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 5042dce683f..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -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() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -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() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 5042dce683f..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -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() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 5042dce683f..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -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() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -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 + ")") } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 5042dce683f..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -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() } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll index a24c08b4f05..a6d8f6b877f 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll @@ -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() { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 5042dce683f..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -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() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -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() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 5042dce683f..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -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() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 5042dce683f..8c210edbe5f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -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() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -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 + ")") } diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index bc105d64066..45a027505b9 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -13,6 +13,7 @@ private import implementations.Strcat private import implementations.Strcpy private import implementations.Strdup private import implementations.Strftime +private import implementations.StdContainer private import implementations.StdString private import implementations.Swap private import implementations.GetDelim diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll new file mode 100644 index 00000000000..40293f72ed0 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll @@ -0,0 +1,102 @@ +/** + * Provides models for C++ containers `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`. + */ + +import semmle.code.cpp.models.interfaces.Taint + +/** + * Additional model for standard container constructors that reference the + * value type of the container (that is, the `T` in `std::vector`). For + * example the fill constructor: + * ``` + * std::vector v(100, potentially_tainted_string); + * ``` + */ +class StdSequenceContainerConstructor extends Constructor, TaintFunction { + StdSequenceContainerConstructor() { + this.getDeclaringType().hasQualifiedName("std", "vector") or + this.getDeclaringType().hasQualifiedName("std", "deque") or + this.getDeclaringType().hasQualifiedName("std", "list") or + this.getDeclaringType().hasQualifiedName("std", "forward_list") + } + + /** + * Gets the index of a parameter to this function that is a reference to the + * value type of the container. + */ + int getAValueTypeParameterIndex() { + getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() = + getDeclaringType().getTemplateArgument(0) // i.e. the `T` of this `std::vector` + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // taint flow from any parameter of the value type to the returned object + input.isParameterDeref(getAValueTypeParameterIndex()) and + output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported. + } +} + +/** + * The standard container functions `push_back` and `push_front`. + */ +class StdSequenceContainerPush extends TaintFunction { + StdSequenceContainerPush() { + this.hasQualifiedName("std", "vector", "push_back") or + this.hasQualifiedName("std", "deque", "push_back") or + this.hasQualifiedName("std", "deque", "push_front") or + this.hasQualifiedName("std", "list", "push_back") or + this.hasQualifiedName("std", "list", "push_front") or + this.hasQualifiedName("std", "forward_list", "push_front") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from parameter to qualifier + input.isParameterDeref(0) and + output.isQualifierObject() + } +} + +/** + * The standard container functions `front` and `back`. + */ +class StdSequenceContainerFrontBack extends TaintFunction { + StdSequenceContainerFrontBack() { + this.hasQualifiedName("std", "array", "front") or + this.hasQualifiedName("std", "array", "back") or + this.hasQualifiedName("std", "vector", "front") or + this.hasQualifiedName("std", "vector", "back") or + this.hasQualifiedName("std", "deque", "front") or + this.hasQualifiedName("std", "deque", "back") or + this.hasQualifiedName("std", "list", "front") or + this.hasQualifiedName("std", "list", "back") or + this.hasQualifiedName("std", "forward_list", "front") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from object to returned reference + input.isQualifierObject() and + output.isReturnValueDeref() + } +} + +/** + * The standard container `swap` functions. + */ +class StdSequenceContainerSwap extends TaintFunction { + StdSequenceContainerSwap() { + this.hasQualifiedName("std", "array", "swap") or + this.hasQualifiedName("std", "vector", "swap") or + this.hasQualifiedName("std", "deque", "swap") or + this.hasQualifiedName("std", "list", "swap") or + this.hasQualifiedName("std", "forward_list", "swap") + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // container1.swap(container2) + input.isQualifierObject() and + output.isParameterDeref(0) + or + input.isParameterDeref(0) and + output.isQualifierObject() + } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll index 9ffef420a19..fa2e37539eb 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -1,10 +1,20 @@ import semmle.code.cpp.models.interfaces.Taint /** - * The standard function `std::string.c_str`. + * The `std::basic_string` template class. + */ +class StdBasicString extends TemplateClass { + StdBasicString() { this.hasQualifiedName("std", "basic_string") } +} + +/** + * 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 @@ -12,3 +22,126 @@ class StdStringCStr extends TaintFunction { output.isReturnValue() } } + +/** + * The `std::string` function `operator+`. + */ +class StdStringPlus extends TaintFunction { + StdStringPlus() { + this.hasQualifiedName("std", "operator+") and + this.getUnspecifiedType() = any(StdBasicString s).getAnInstantiation() + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from parameters to return value + ( + input.isParameterDeref(0) or + input.isParameterDeref(1) + ) and + output.isReturnValue() + } +} + +/** + * 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") or + this.hasQualifiedName("std", "basic_string", "insert") or + this.hasQualifiedName("std", "basic_string", "replace") + } + + /** + * 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 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 + ( + output.isQualifierObject() or + output.isReturnValueDeref() + ) + } +} + +/** + * 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() + } +} diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index 9ebd2b2219a..db6293eb05d 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -44,6 +44,7 @@ import cpp private import RangeAnalysisUtils +private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr import RangeSSA import SimpleRangeAnalysisCached private import NanAnalysis @@ -126,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() @@ -135,7 +136,7 @@ private class UnsignedBitwiseAndExpr extends BitwiseAndExpr { .getUnderlyingType() .(IntegralType) .isUnsigned() or - getRightOperand().getFullyConverted().getValue().toInt() >= 0 + getValue(getRightOperand().getFullyConverted()).toInt() >= 0 ) } } @@ -156,6 +157,92 @@ 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() 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. */ private predicate analyzableExpr(Expr e) { // The type of the expression must be arithmetic. We reuse the logic in @@ -164,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 @@ -178,20 +265,22 @@ private predicate analyzableExpr(Expr e) { or e instanceof SubExpr or + e instanceof UnsignedMulExpr + or e instanceof AssignExpr or e instanceof AssignAddExpr 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 @@ -206,7 +295,10 @@ 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 ) } @@ -227,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 @@ -258,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)) @@ -278,6 +380,10 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria or exists(SubExpr subExpr | e = subExpr | exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar)) or + exists(UnsignedMulExpr mulExpr | e = mulExpr | + exprDependsOnDef(mulExpr.getAnOperand(), srcDef, srcVar) + ) + or exists(AssignExpr addExpr | e = addExpr | exprDependsOnDef(addExpr.getRValue(), srcDef, srcVar)) or exists(AssignAddExpr addExpr | e = addExpr | @@ -288,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 `&` @@ -313,11 +419,21 @@ 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 e = srcDef.getAUse(srcVar) + or + // A modeled expression for range analysis + exists(SimpleRangeAnalysisExpr rae | rae = e | + rae.dependsOnDef(srcDef, srcVar) + or + exists(Expr child | + rae.dependsOnChild(child) and + exprDependsOnDef(child, srcDef, srcVar) + ) + ) } /** @@ -381,9 +497,17 @@ private predicate assignmentDef(RangeSsaDefinition def, StackVariable v, Expr ex ) } -/** See comment above sourceDef. */ +/** See comment above assignmentDef. */ private predicate analyzableDef(RangeSsaDefinition def, StackVariable v) { - assignmentDef(def, v, _) or defDependsOnDef(def, v, _, _) + assignmentDef(def, v, _) + or + analyzableExpr(def.(AssignOperation)) and + v = def.getAVariable() + or + analyzableExpr(def.(CrementOperation)) and + v = def.getAVariable() + or + phiDependsOnDef(def, v, _, _) } /** @@ -435,13 +559,6 @@ private float addRoundingDownSmall(float x, float small) { if (x + small) - x > small then result = (x + small).nextDown() else result = (x + small) } -/** - * Gets the truncated lower bounds of the fully converted expression. - */ -private float getFullyConvertedLowerBounds(Expr expr) { - result = getTruncatedLowerBounds(expr.getFullyConverted()) -} - /** * Gets the lower bounds of the expression. * @@ -488,13 +605,6 @@ private float getTruncatedLowerBounds(Expr expr) { result = exprMinVal(expr) } -/** - * Gets the truncated upper bounds of the fully converted expression. - */ -private float getFullyConvertedUpperBounds(Expr expr) { - result = getTruncatedUpperBounds(expr.getFullyConverted()) -} - /** * Gets the upper bounds of the expression. * @@ -562,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 | @@ -625,6 +736,13 @@ private float getLowerBoundsImpl(Expr expr) { result = addRoundingDown(xLow, -yHigh) ) or + exists(UnsignedMulExpr mulExpr, float xLow, float yLow | + expr = mulExpr and + xLow = getFullyConvertedLowerBounds(mulExpr.getLeftOperand()) and + yLow = getFullyConvertedLowerBounds(mulExpr.getRightOperand()) and + result = xLow * yLow + ) + or exists(AssignExpr assign | expr = assign and result = getFullyConvertedLowerBounds(assign.getRValue()) @@ -644,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 @@ -688,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`. @@ -711,7 +838,9 @@ private float getLowerBoundsImpl(Expr expr) { or // Use SSA to get the lower bounds for a variable use. exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | - result = getDefLowerBounds(def, v) + result = getDefLowerBounds(def, v) and + // Not explicitly modeled by a SimpleRangeAnalysisExpr + not expr instanceof SimpleRangeAnalysisExpr ) or // unsigned `&` (tighter bounds may exist) @@ -724,22 +853,29 @@ 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 + // A modeled expression for range analysis + exists(SimpleRangeAnalysisExpr rangeAnalysisExpr | + rangeAnalysisExpr = expr and + result = rangeAnalysisExpr.getLowerBounds() + ) } /** 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 | @@ -794,6 +930,13 @@ private float getUpperBoundsImpl(Expr expr) { result = addRoundingUp(xHigh, -yLow) ) or + exists(UnsignedMulExpr mulExpr, float xHigh, float yHigh | + expr = mulExpr and + xHigh = getFullyConvertedUpperBounds(mulExpr.getLeftOperand()) and + yHigh = getFullyConvertedUpperBounds(mulExpr.getRightOperand()) and + result = xHigh * yHigh + ) + or exists(AssignExpr assign | expr = assign and result = getFullyConvertedUpperBounds(assign.getRValue()) @@ -813,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 @@ -855,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`. @@ -878,7 +1030,9 @@ private float getUpperBoundsImpl(Expr expr) { or // Use SSA to get the upper bounds for a variable use. exists(RangeSsaDefinition def, StackVariable v | expr = def.getAUse(v) | - result = getDefUpperBounds(def, v) + result = getDefUpperBounds(def, v) and + // Not explicitly modeled by a SimpleRangeAnalysisExpr + not expr instanceof SimpleRangeAnalysisExpr ) or // unsigned `&` (tighter bounds may exist) @@ -893,9 +1047,15 @@ 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 + // A modeled expression for range analysis + exists(SimpleRangeAnalysisExpr rangeAnalysisExpr | + rangeAnalysisExpr = expr and + result = rangeAnalysisExpr.getUpperBounds() + ) } /** @@ -1041,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 @@ -1083,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 @@ -1480,3 +1684,25 @@ private module SimpleRangeAnalysisCached { convertedExprMightOverflowPositively(expr) } } + +/** + * INTERNAL: do not use. This module contains utilities for use in the + * experimental `SimpleRangeAnalysisExpr` module. + */ +module SimpleRangeAnalysisInternal { + /** + * Gets the truncated lower bounds of the fully converted expression. + */ + float getFullyConvertedLowerBounds(Expr expr) { + result = getTruncatedLowerBounds(expr.getFullyConverted()) + } + + /** + * Gets the truncated upper bounds of the fully converted expression. + */ + float getFullyConvertedUpperBounds(Expr expr) { + result = getTruncatedUpperBounds(expr.getFullyConverted()) + } +} + +private import SimpleRangeAnalysisInternal diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c new file mode 100644 index 00000000000..42f7574996c --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.c @@ -0,0 +1,9 @@ +/// Adds its arguments (has custom modeling in QL) +int custom_add_function(int a, int b); + +int test_extensibility_add(int x) { + if (x >= -10 && x <= 10) { + int result = custom_add_function(x, 100); + return result; // 90 .. 110 + } +} diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected new file mode 100644 index 00000000000..463ac9ea06c --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.expected @@ -0,0 +1,4 @@ +| extensibility.c:5:7:5:7 | x | -2.147483648E9 | 2.147483647E9 | +| extensibility.c:5:19:5:19 | x | -10.0 | 2.147483647E9 | +| extensibility.c:6:38:6:38 | x | -10.0 | 10.0 | +| extensibility.c:7:12:7:17 | result | 90.0 | 110.0 | diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql new file mode 100644 index 00000000000..710a89ad7fa --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/extensibility/extensibility.ql @@ -0,0 +1,32 @@ +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis +import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr + +class CustomAddFunctionCall extends SimpleRangeAnalysisExpr, FunctionCall { + CustomAddFunctionCall() { this.getTarget().hasGlobalName("custom_add_function") } + + override float getLowerBounds() { + exists(float lower0, float lower1 | + lower0 = getFullyConvertedLowerBounds(this.getArgument(0)) and + lower1 = getFullyConvertedLowerBounds(this.getArgument(1)) and + // Note: this rounds toward 0, not -Inf as it should + result = lower0 + lower1 + ) + } + + override float getUpperBounds() { + exists(float upper0, float upper1 | + upper0 = getFullyConvertedUpperBounds(this.getArgument(0)) and + upper1 = getFullyConvertedUpperBounds(this.getArgument(1)) and + // Note: this rounds toward 0, not Inf as it should + result = upper0 + upper1 + ) + } + + override predicate dependsOnChild(Expr child) { child = this.getAnArgument() } +} + +from VariableAccess expr, float lower, float upper +where + lower = lowerBound(expr) and + upper = upperBound(expr) +select expr, lower, upper diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index ed26a2de21d..e86a57f2202 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -308,205 +308,413 @@ | movableclass.cpp:65:13:65:18 | call to source | movableclass.cpp:65:13:65:20 | call to MyMovableClass | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:8:65:9 | ref arg s3 | TAINT | | movableclass.cpp:65:13:65:20 | call to MyMovableClass | movableclass.cpp:65:11:65:11 | call to operator= | TAINT | -| stl.cpp:97:12:97:17 | call to source | stl.cpp:101:7:101:7 | a | | -| stl.cpp:98:16:98:20 | 123 | stl.cpp:98:16:98:21 | call to basic_string | TAINT | -| stl.cpp:98:16:98:21 | call to basic_string | stl.cpp:102:7:102:7 | b | | -| stl.cpp:98:16:98:21 | call to basic_string | stl.cpp:104:7:104:7 | b | | -| stl.cpp:99:16:99:21 | call to source | stl.cpp:99:16:99:24 | call to basic_string | TAINT | -| stl.cpp:99:16:99:24 | call to basic_string | stl.cpp:103:7:103:7 | c | | -| stl.cpp:99:16:99:24 | call to basic_string | stl.cpp:105:7:105:7 | c | | -| stl.cpp:104:7:104:7 | b | stl.cpp:104:9:104:13 | call to c_str | TAINT | -| stl.cpp:105:7:105:7 | c | stl.cpp:105:9:105:13 | call to c_str | TAINT | -| stl.cpp:110:20:110:22 | call to basic_stringstream | stl.cpp:113:2:113:4 | ss1 | | -| stl.cpp:110:20:110:22 | call to basic_stringstream | stl.cpp:119:7:119:9 | ss1 | | -| stl.cpp:110:20:110:22 | call to basic_stringstream | stl.cpp:124:7:124:9 | ss1 | | -| stl.cpp:110:25:110:27 | call to basic_stringstream | stl.cpp:114:2:114:4 | ss2 | | -| stl.cpp:110:25:110:27 | call to basic_stringstream | stl.cpp:120:7:120:9 | ss2 | | -| stl.cpp:110:25:110:27 | call to basic_stringstream | stl.cpp:125:7:125:9 | ss2 | | -| stl.cpp:110:30:110:32 | call to basic_stringstream | stl.cpp:115:2:115:4 | ss3 | | -| stl.cpp:110:30:110:32 | call to basic_stringstream | stl.cpp:121:7:121:9 | ss3 | | -| stl.cpp:110:30:110:32 | call to basic_stringstream | stl.cpp:126:7:126:9 | ss3 | | -| stl.cpp:110:35:110:37 | call to basic_stringstream | stl.cpp:116:2:116:4 | ss4 | | -| stl.cpp:110:35:110:37 | call to basic_stringstream | stl.cpp:122:7:122:9 | ss4 | | -| stl.cpp:110:35:110:37 | call to basic_stringstream | stl.cpp:127:7:127:9 | ss4 | | -| stl.cpp:110:40:110:42 | call to basic_stringstream | stl.cpp:117:2:117:4 | ss5 | | -| stl.cpp:110:40:110:42 | call to basic_stringstream | stl.cpp:123:7:123:9 | ss5 | | -| stl.cpp:110:40:110:42 | call to basic_stringstream | stl.cpp:128:7:128:9 | ss5 | | -| stl.cpp:111:16:111:21 | call to source | stl.cpp:111:16:111:24 | call to basic_string | TAINT | -| stl.cpp:111:16:111:24 | call to basic_string | stl.cpp:117:9:117:9 | t | | -| stl.cpp:113:2:113:4 | ref arg ss1 | stl.cpp:119:7:119:9 | ss1 | | -| stl.cpp:113:2:113:4 | ref arg ss1 | stl.cpp:124:7:124:9 | ss1 | | -| stl.cpp:114:2:114:4 | ref arg ss2 | stl.cpp:120:7:120:9 | ss2 | | -| stl.cpp:114:2:114:4 | ref arg ss2 | stl.cpp:125:7:125:9 | ss2 | | -| stl.cpp:115:2:115:4 | ref arg ss3 | stl.cpp:121:7:121:9 | ss3 | | -| stl.cpp:115:2:115:4 | ref arg ss3 | stl.cpp:126:7:126:9 | ss3 | | -| stl.cpp:116:2:116:4 | ref arg ss4 | stl.cpp:122:7:122:9 | ss4 | | -| stl.cpp:116:2:116:4 | ref arg ss4 | stl.cpp:127:7:127:9 | ss4 | | -| stl.cpp:117:2:117:4 | ref arg ss5 | stl.cpp:123:7:123:9 | ss5 | | -| stl.cpp:117:2:117:4 | ref arg ss5 | stl.cpp:128:7:128:9 | ss5 | | -| stl.cpp:131:32:131:37 | source | stl.cpp:136:9:136:14 | source | | -| stl.cpp:133:20:133:22 | call to basic_stringstream | stl.cpp:135:2:135:4 | ss1 | | -| stl.cpp:133:20:133:22 | call to basic_stringstream | stl.cpp:138:7:138:9 | ss1 | | -| stl.cpp:133:20:133:22 | call to basic_stringstream | stl.cpp:140:7:140:9 | ss1 | | -| stl.cpp:133:25:133:27 | call to basic_stringstream | stl.cpp:136:2:136:4 | ss2 | | -| stl.cpp:133:25:133:27 | call to basic_stringstream | stl.cpp:139:7:139:9 | ss2 | | -| stl.cpp:133:25:133:27 | call to basic_stringstream | stl.cpp:141:7:141:9 | ss2 | | -| stl.cpp:135:2:135:4 | ref arg ss1 | stl.cpp:138:7:138:9 | ss1 | | -| stl.cpp:135:2:135:4 | ref arg ss1 | stl.cpp:140:7:140:9 | ss1 | | -| stl.cpp:136:2:136:4 | ref arg ss2 | stl.cpp:139:7:139:9 | ss2 | | -| stl.cpp:136:2:136:4 | ref arg ss2 | stl.cpp:141:7:141:9 | ss2 | | -| stl.cpp:154:16:154:28 | call to basic_string | stl.cpp:155:7:155:11 | path1 | | -| stl.cpp:154:17:154:26 | call to user_input | stl.cpp:154:16:154:28 | call to basic_string | TAINT | -| stl.cpp:155:7:155:11 | path1 | stl.cpp:155:13:155:17 | call to c_str | TAINT | -| stl.cpp:158:10:158:19 | call to user_input | stl.cpp:158:10:158:21 | call to basic_string | TAINT | -| stl.cpp:158:10:158:21 | call to basic_string | stl.cpp:158:2:158:21 | ... = ... | | -| stl.cpp:158:10:158:21 | call to basic_string | stl.cpp:159:7:159:11 | path2 | | -| stl.cpp:159:7:159:11 | path2 | stl.cpp:159:13:159:17 | call to c_str | TAINT | -| stl.cpp:161:15:161:24 | call to user_input | stl.cpp:161:15:161:27 | call to basic_string | TAINT | -| stl.cpp:161:15:161:27 | call to basic_string | stl.cpp:162:7:162:11 | path3 | | -| stl.cpp:162:7:162:11 | path3 | stl.cpp:162:13:162:17 | call to c_str | TAINT | -| stl.cpp:167:19:167:24 | call to source | stl.cpp:170:17:170:18 | cs | | -| stl.cpp:167:19:167:24 | call to source | stl.cpp:172:7:172:8 | cs | | -| stl.cpp:170:17:170:18 | cs | stl.cpp:170:17:170:19 | call to basic_string | TAINT | -| stl.cpp:170:17:170:19 | call to basic_string | stl.cpp:173:7:173:8 | ss | | -| stl.cpp:178:19:178:24 | call to source | stl.cpp:181:17:181:18 | cs | | -| stl.cpp:181:17:181:18 | cs | stl.cpp:181:17:181:19 | call to basic_string | TAINT | -| stl.cpp:181:17:181:19 | call to basic_string | stl.cpp:184:7:184:8 | ss | | -| stl.cpp:181:17:181:19 | call to basic_string | stl.cpp:187:7:187:8 | ss | | -| stl.cpp:184:7:184:8 | ss | stl.cpp:184:10:184:14 | call to c_str | TAINT | -| stl.cpp:184:10:184:14 | call to c_str | stl.cpp:184:2:184:16 | ... = ... | | -| stl.cpp:184:10:184:14 | call to c_str | stl.cpp:186:7:186:8 | cs | | -| stl.cpp:193:18:193:24 | hello | stl.cpp:193:18:193:25 | call to basic_string | TAINT | -| stl.cpp:193:18:193:25 | call to basic_string | stl.cpp:198:8:198:9 | s1 | | -| stl.cpp:194:19:194:26 | call to basic_string | stl.cpp:199:8:199:9 | s2 | | -| stl.cpp:194:20:194:26 | hello | stl.cpp:194:19:194:26 | call to basic_string | TAINT | -| stl.cpp:196:8:196:14 | call to basic_string | stl.cpp:196:3:196:14 | ... = ... | | -| stl.cpp:196:8:196:14 | call to basic_string | stl.cpp:200:8:200:9 | s3 | | -| stl.cpp:196:8:196:14 | hello | stl.cpp:196:8:196:14 | call to basic_string | TAINT | -| stl.cpp:204:18:204:23 | call to source | stl.cpp:204:18:204:26 | call to basic_string | TAINT | -| stl.cpp:204:18:204:26 | call to basic_string | stl.cpp:209:8:209:9 | s1 | | -| stl.cpp:205:19:205:27 | call to basic_string | stl.cpp:210:8:210:9 | s2 | | -| stl.cpp:205:20:205:25 | call to source | stl.cpp:205:19:205:27 | call to basic_string | TAINT | -| stl.cpp:207:8:207:13 | call to source | stl.cpp:207:8:207:15 | call to basic_string | TAINT | -| stl.cpp:207:8:207:15 | call to basic_string | stl.cpp:207:3:207:15 | ... = ... | | -| stl.cpp:207:8:207:15 | call to basic_string | stl.cpp:211:8:211:9 | s3 | | -| stl.cpp:215:15:215:16 | call to basic_string | stl.cpp:216:20:216:21 | s1 | | -| stl.cpp:215:15:215:16 | call to basic_string | stl.cpp:218:8:218:9 | s1 | | -| stl.cpp:215:15:215:16 | call to basic_string | stl.cpp:220:8:220:9 | s1 | | -| stl.cpp:216:20:216:21 | s1 | stl.cpp:221:8:221:9 | s2 | | -| stl.cpp:218:8:218:9 | s1 | stl.cpp:218:3:218:9 | ... = ... | | -| stl.cpp:218:8:218:9 | s1 | stl.cpp:222:8:222:9 | s3 | | -| stl.cpp:226:19:226:40 | call to basic_string | stl.cpp:230:8:230:9 | s1 | | -| stl.cpp:226:32:226:37 | call to source | stl.cpp:226:19:226:40 | call to basic_string | TAINT | -| stl.cpp:228:8:228:28 | call to basic_string | stl.cpp:228:3:228:28 | ... = ... | | -| stl.cpp:228:8:228:28 | call to basic_string | stl.cpp:231:8:231:9 | s2 | | -| stl.cpp:228:20:228:25 | call to source | stl.cpp:228:8:228:28 | call to basic_string | TAINT | -| stl.cpp:238:16:238:21 | call to source | stl.cpp:238:16:238:24 | call to basic_string | TAINT | -| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:239:15:239:15 | s | | -| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:243:33:243:33 | s | | -| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:243:50:243:50 | s | | -| stl.cpp:238:16:238:24 | call to basic_string | stl.cpp:247:16:247:16 | s | | -| stl.cpp:239:15:239:15 | call to begin | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | call to begin | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | call to begin | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | call to end | stl.cpp:239:15:239:15 | (__end) | | -| stl.cpp:239:15:239:15 | call to operator* | stl.cpp:240:8:240:8 | c | | -| stl.cpp:239:15:239:15 | ref arg (__begin) | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | ref arg (__begin) | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | ref arg (__begin) | stl.cpp:239:15:239:15 | (__begin) | | -| stl.cpp:239:15:239:15 | ref arg (__range) | stl.cpp:239:15:239:15 | (__range) | | -| stl.cpp:239:15:239:15 | s | stl.cpp:239:15:239:15 | (__range) | | -| stl.cpp:239:15:239:15 | s | stl.cpp:239:15:239:15 | (__range) | | -| stl.cpp:239:15:239:15 | s | stl.cpp:239:15:239:15 | call to operator* | TAINT | -| stl.cpp:243:33:243:33 | ref arg s | stl.cpp:243:50:243:50 | s | | -| stl.cpp:243:33:243:33 | ref arg s | stl.cpp:247:16:247:16 | s | | -| stl.cpp:243:35:243:39 | call to begin | stl.cpp:243:44:243:45 | it | | -| stl.cpp:243:35:243:39 | call to begin | stl.cpp:243:61:243:62 | it | | -| stl.cpp:243:35:243:39 | call to begin | stl.cpp:244:9:244:10 | it | | -| stl.cpp:243:50:243:50 | ref arg s | stl.cpp:243:50:243:50 | s | | -| stl.cpp:243:50:243:50 | ref arg s | stl.cpp:247:16:247:16 | s | | -| stl.cpp:243:61:243:62 | ref arg it | stl.cpp:243:44:243:45 | it | | -| stl.cpp:243:61:243:62 | ref arg it | stl.cpp:243:61:243:62 | it | | -| stl.cpp:243:61:243:62 | ref arg it | stl.cpp:244:9:244:10 | it | | -| stl.cpp:247:16:247:16 | call to begin | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | call to begin | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | call to begin | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | call to end | stl.cpp:247:16:247:16 | (__end) | | -| stl.cpp:247:16:247:16 | call to operator* | stl.cpp:248:8:248:8 | c | | -| stl.cpp:247:16:247:16 | ref arg (__begin) | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | ref arg (__begin) | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | ref arg (__begin) | stl.cpp:247:16:247:16 | (__begin) | | -| stl.cpp:247:16:247:16 | ref arg (__range) | stl.cpp:247:16:247:16 | (__range) | | -| stl.cpp:247:16:247:16 | s | stl.cpp:247:16:247:16 | (__range) | | -| stl.cpp:247:16:247:16 | s | stl.cpp:247:16:247:16 | (__range) | | -| stl.cpp:247:16:247:16 | s | stl.cpp:247:16:247:16 | call to operator* | TAINT | -| stl.cpp:251:28:251:33 | call to source | stl.cpp:251:28:251:36 | call to basic_string | TAINT | -| stl.cpp:251:28:251:36 | call to basic_string | stl.cpp:252:22:252:28 | const_s | | -| stl.cpp:252:22:252:22 | call to begin | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | call to begin | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | call to begin | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | call to end | stl.cpp:252:22:252:22 | (__end) | | -| stl.cpp:252:22:252:22 | call to operator* | stl.cpp:253:8:253:8 | c | | -| stl.cpp:252:22:252:22 | ref arg (__begin) | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | ref arg (__begin) | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:22 | ref arg (__begin) | stl.cpp:252:22:252:22 | (__begin) | | -| stl.cpp:252:22:252:28 | const_s | stl.cpp:252:22:252:22 | (__range) | | -| stl.cpp:252:22:252:28 | const_s | stl.cpp:252:22:252:22 | (__range) | | -| stl.cpp:252:22:252:28 | const_s | stl.cpp:252:22:252:22 | call to operator* | TAINT | -| stl.cpp:288:43:288:49 | source1 | stl.cpp:292:21:292:27 | source1 | | -| stl.cpp:288:43:288:49 | source1 | stl.cpp:306:33:306:39 | source1 | | -| stl.cpp:292:21:292:27 | source1 | stl.cpp:292:21:292:28 | call to vector | TAINT | -| stl.cpp:292:21:292:28 | call to vector | stl.cpp:294:14:294:14 | v | | -| stl.cpp:292:21:292:28 | call to vector | stl.cpp:298:38:298:38 | v | | -| stl.cpp:292:21:292:28 | call to vector | stl.cpp:298:55:298:55 | v | | -| stl.cpp:292:21:292:28 | call to vector | stl.cpp:302:15:302:15 | v | | -| stl.cpp:294:14:294:14 | call to begin | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | call to begin | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | call to begin | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | call to end | stl.cpp:294:14:294:14 | (__end) | | -| stl.cpp:294:14:294:14 | call to operator* | stl.cpp:295:8:295:8 | x | | -| stl.cpp:294:14:294:14 | ref arg (__begin) | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | ref arg (__begin) | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | ref arg (__begin) | stl.cpp:294:14:294:14 | (__begin) | | -| stl.cpp:294:14:294:14 | ref arg (__range) | stl.cpp:294:14:294:14 | (__range) | | -| stl.cpp:294:14:294:14 | v | stl.cpp:294:14:294:14 | (__range) | | -| stl.cpp:294:14:294:14 | v | stl.cpp:294:14:294:14 | (__range) | | -| stl.cpp:294:14:294:14 | v | stl.cpp:294:14:294:14 | call to operator* | TAINT | -| stl.cpp:298:38:298:38 | ref arg v | stl.cpp:298:55:298:55 | v | | -| stl.cpp:298:38:298:38 | ref arg v | stl.cpp:302:15:302:15 | v | | -| stl.cpp:298:40:298:44 | call to begin | stl.cpp:298:49:298:50 | it | | -| stl.cpp:298:40:298:44 | call to begin | stl.cpp:298:66:298:67 | it | | -| stl.cpp:298:40:298:44 | call to begin | stl.cpp:299:9:299:10 | it | | -| stl.cpp:298:55:298:55 | ref arg v | stl.cpp:298:55:298:55 | v | | -| stl.cpp:298:55:298:55 | ref arg v | stl.cpp:302:15:302:15 | v | | -| stl.cpp:298:66:298:67 | ref arg it | stl.cpp:298:49:298:50 | it | | -| stl.cpp:298:66:298:67 | ref arg it | stl.cpp:298:66:298:67 | it | | -| stl.cpp:298:66:298:67 | ref arg it | stl.cpp:299:9:299:10 | it | | -| stl.cpp:302:15:302:15 | call to begin | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | call to begin | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | call to begin | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | call to end | stl.cpp:302:15:302:15 | (__end) | | -| stl.cpp:302:15:302:15 | call to operator* | stl.cpp:303:8:303:8 | x | | -| stl.cpp:302:15:302:15 | ref arg (__begin) | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | ref arg (__begin) | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | ref arg (__begin) | stl.cpp:302:15:302:15 | (__begin) | | -| stl.cpp:302:15:302:15 | ref arg (__range) | stl.cpp:302:15:302:15 | (__range) | | -| stl.cpp:302:15:302:15 | v | stl.cpp:302:15:302:15 | (__range) | | -| stl.cpp:302:15:302:15 | v | stl.cpp:302:15:302:15 | (__range) | | -| stl.cpp:302:15:302:15 | v | stl.cpp:302:15:302:15 | call to operator* | TAINT | -| stl.cpp:306:33:306:39 | source1 | stl.cpp:306:33:306:40 | call to vector | TAINT | -| stl.cpp:306:33:306:40 | call to vector | stl.cpp:307:21:307:27 | const_v | | -| stl.cpp:307:21:307:21 | call to begin | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | call to begin | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | call to begin | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | call to end | stl.cpp:307:21:307:21 | (__end) | | -| stl.cpp:307:21:307:21 | call to operator* | stl.cpp:308:8:308:8 | x | | -| stl.cpp:307:21:307:21 | ref arg (__begin) | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | ref arg (__begin) | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:21 | ref arg (__begin) | stl.cpp:307:21:307:21 | (__begin) | | -| stl.cpp:307:21:307:27 | const_v | stl.cpp:307:21:307:21 | (__range) | | -| stl.cpp:307:21:307:27 | const_v | stl.cpp:307:21:307:21 | (__range) | | -| stl.cpp:307:21:307:27 | const_v | stl.cpp:307:21:307:21 | call to operator* | TAINT | +| string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | | +| string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT | +| string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | | +| string.cpp:25:16:25:21 | call to basic_string | string.cpp:31:7:31:7 | b | | +| string.cpp:26:16:26:21 | call to source | string.cpp:26:16:26:24 | call to basic_string | TAINT | +| string.cpp:26:16:26:24 | call to basic_string | string.cpp:30:7:30:7 | c | | +| string.cpp:26:16:26:24 | call to basic_string | string.cpp:32:7:32:7 | c | | +| string.cpp:31:7:31:7 | b | string.cpp:31:9:31:13 | call to c_str | TAINT | +| string.cpp:32:7:32:7 | c | string.cpp:32:9:32:13 | call to c_str | TAINT | +| string.cpp:37:16:37:28 | call to basic_string | string.cpp:38:7:38:11 | path1 | | +| string.cpp:37:17:37:26 | call to user_input | string.cpp:37:16:37:28 | call to basic_string | TAINT | +| string.cpp:38:7:38:11 | path1 | string.cpp:38:13:38:17 | call to c_str | TAINT | +| string.cpp:41:10:41:19 | call to user_input | string.cpp:41:10:41:21 | call to basic_string | TAINT | +| string.cpp:41:10:41:21 | call to basic_string | string.cpp:41:2:41:21 | ... = ... | | +| string.cpp:41:10:41:21 | call to basic_string | string.cpp:42:7:42:11 | path2 | | +| string.cpp:42:7:42:11 | path2 | string.cpp:42:13:42:17 | call to c_str | TAINT | +| string.cpp:44:15:44:24 | call to user_input | string.cpp:44:15:44:27 | call to basic_string | TAINT | +| string.cpp:44:15:44:27 | call to basic_string | string.cpp:45:7:45:11 | path3 | | +| string.cpp:45:7:45:11 | path3 | string.cpp:45:13:45:17 | call to c_str | TAINT | +| string.cpp:50:19:50:24 | call to source | string.cpp:53:17:53:18 | cs | | +| string.cpp:50:19:50:24 | call to source | string.cpp:55:7:55:8 | cs | | +| string.cpp:53:17:53:18 | cs | string.cpp:53:17:53:19 | call to basic_string | TAINT | +| string.cpp:53:17:53:19 | call to basic_string | string.cpp:56:7:56:8 | ss | | +| string.cpp:61:19:61:24 | call to source | string.cpp:64:17:64:18 | cs | | +| string.cpp:64:17:64:18 | cs | string.cpp:64:17:64:19 | call to basic_string | TAINT | +| string.cpp:64:17:64:19 | call to basic_string | string.cpp:67:7:67:8 | ss | | +| string.cpp:64:17:64:19 | call to basic_string | string.cpp:70:7:70:8 | ss | | +| string.cpp:67:7:67:8 | ss | string.cpp:67:10:67:14 | call to c_str | TAINT | +| string.cpp:67:10:67:14 | call to c_str | string.cpp:67:2:67:16 | ... = ... | | +| string.cpp:67:10:67:14 | call to c_str | string.cpp:69:7:69:8 | cs | | +| string.cpp:76:18:76:24 | hello | string.cpp:76:18:76:25 | call to basic_string | TAINT | +| string.cpp:76:18:76:25 | call to basic_string | string.cpp:81:8:81:9 | s1 | | +| string.cpp:77:19:77:26 | call to basic_string | string.cpp:82:8:82:9 | s2 | | +| string.cpp:77:20:77:26 | hello | string.cpp:77:19:77:26 | call to basic_string | TAINT | +| string.cpp:79:8:79:14 | call to basic_string | string.cpp:79:3:79:14 | ... = ... | | +| string.cpp:79:8:79:14 | call to basic_string | string.cpp:83:8:83:9 | s3 | | +| string.cpp:79:8:79:14 | hello | string.cpp:79:8:79:14 | call to basic_string | TAINT | +| string.cpp:87:18:87:23 | call to source | string.cpp:87:18:87:26 | call to basic_string | TAINT | +| string.cpp:87:18:87:26 | call to basic_string | string.cpp:92:8:92:9 | s1 | | +| string.cpp:88:19:88:27 | call to basic_string | string.cpp:93:8:93:9 | s2 | | +| string.cpp:88:20:88:25 | call to source | string.cpp:88:19:88:27 | call to basic_string | TAINT | +| string.cpp:90:8:90:13 | call to source | string.cpp:90:8:90:15 | call to basic_string | TAINT | +| string.cpp:90:8:90:15 | call to basic_string | string.cpp:90:3:90:15 | ... = ... | | +| string.cpp:90:8:90:15 | call to basic_string | string.cpp:94:8:94:9 | s3 | | +| string.cpp:98:15:98:16 | call to basic_string | string.cpp:99:20:99:21 | s1 | | +| string.cpp:98:15:98:16 | call to basic_string | string.cpp:101:8:101:9 | s1 | | +| string.cpp:98:15:98:16 | call to basic_string | string.cpp:103:8:103:9 | s1 | | +| string.cpp:99:20:99:21 | s1 | string.cpp:104:8:104:9 | s2 | | +| string.cpp:101:8:101:9 | s1 | string.cpp:101:3:101:9 | ... = ... | | +| string.cpp:101:8:101:9 | s1 | string.cpp:105:8:105:9 | s3 | | +| string.cpp:109:19:109:40 | call to basic_string | string.cpp:113:8:113:9 | s1 | | +| string.cpp:109:32:109:37 | call to source | string.cpp:109:19:109:40 | call to basic_string | TAINT | +| string.cpp:111:8:111:28 | call to basic_string | string.cpp:111:3:111:28 | ... = ... | | +| string.cpp:111:8:111:28 | call to basic_string | string.cpp:114:8:114:9 | s2 | | +| string.cpp:111:20:111:25 | call to source | string.cpp:111:8:111:28 | call to basic_string | TAINT | +| string.cpp:119:16:119:21 | call to source | string.cpp:119:16:119:24 | call to basic_string | TAINT | +| string.cpp:119:16:119:24 | call to basic_string | string.cpp:120:15:120:15 | s | | +| string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:33:124:33 | s | | +| string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:50:124:50 | s | | +| string.cpp:119:16:119:24 | call to basic_string | string.cpp:128:16:128:16 | s | | +| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | call to end | string.cpp:120:15:120:15 | (__end) | | +| string.cpp:120:15:120:15 | call to operator* | string.cpp:121:8:121:8 | c | | +| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | ref arg (__begin) | string.cpp:120:15:120:15 | (__begin) | | +| string.cpp:120:15:120:15 | ref arg (__range) | string.cpp:120:15:120:15 | (__range) | | +| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | (__range) | | +| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | (__range) | | +| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | call to operator* | TAINT | +| string.cpp:124:33:124:33 | ref arg s | string.cpp:124:50:124:50 | s | | +| string.cpp:124:33:124:33 | ref arg s | string.cpp:128:16:128:16 | s | | +| string.cpp:124:35:124:39 | call to begin | string.cpp:124:44:124:45 | it | | +| string.cpp:124:35:124:39 | call to begin | string.cpp:124:61:124:62 | it | | +| string.cpp:124:35:124:39 | call to begin | string.cpp:125:9:125:10 | it | | +| string.cpp:124:50:124:50 | ref arg s | string.cpp:124:50:124:50 | s | | +| string.cpp:124:50:124:50 | ref arg s | string.cpp:128:16:128:16 | s | | +| string.cpp:124:61:124:62 | ref arg it | string.cpp:124:44:124:45 | it | | +| string.cpp:124:61:124:62 | ref arg it | string.cpp:124:61:124:62 | it | | +| string.cpp:124:61:124:62 | ref arg it | string.cpp:125:9:125:10 | it | | +| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | call to end | string.cpp:128:16:128:16 | (__end) | | +| string.cpp:128:16:128:16 | call to operator* | string.cpp:129:8:129:8 | c | | +| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | ref arg (__begin) | string.cpp:128:16:128:16 | (__begin) | | +| string.cpp:128:16:128:16 | ref arg (__range) | string.cpp:128:16:128:16 | (__range) | | +| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | (__range) | | +| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | (__range) | | +| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | call to operator* | TAINT | +| string.cpp:132:28:132:33 | call to source | string.cpp:132:28:132:36 | call to basic_string | TAINT | +| string.cpp:132:28:132:36 | call to basic_string | string.cpp:133:22:133:28 | const_s | | +| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | call to end | string.cpp:133:22:133:22 | (__end) | | +| string.cpp:133:22:133:22 | call to operator* | string.cpp:134:8:134:8 | c | | +| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:22 | ref arg (__begin) | string.cpp:133:22:133:22 | (__begin) | | +| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | (__range) | | +| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | (__range) | | +| string.cpp:133:22:133:28 | const_s | string.cpp:133:22:133:22 | call to operator* | TAINT | +| string.cpp:140:18:140:24 | hello | string.cpp:140:18:140:25 | call to basic_string | TAINT | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:143:8:143:9 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:143:13:143:14 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:144:8:144:9 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:145:13:145:14 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:148:8:148:9 | s1 | | +| string.cpp:140:18:140:25 | call to basic_string | string.cpp:149:8:149:9 | s1 | | +| string.cpp:141:18:141:23 | call to source | string.cpp:141:18:141:26 | call to basic_string | TAINT | +| string.cpp:141:18:141:26 | call to basic_string | string.cpp:144:13:144:14 | s2 | | +| string.cpp:141:18:141:26 | call to basic_string | string.cpp:145:8:145:9 | s2 | | +| string.cpp:141:18:141:26 | call to basic_string | string.cpp:146:8:146:9 | s2 | | +| string.cpp:141:18:141:26 | call to basic_string | string.cpp:146:13:146:14 | s2 | | +| string.cpp:143:8:143:9 | s1 | string.cpp:143:11:143:11 | call to operator+ | TAINT | +| string.cpp:143:13:143:14 | s1 | string.cpp:143:11:143:11 | call to operator+ | TAINT | +| string.cpp:144:8:144:9 | s1 | string.cpp:144:11:144:11 | call to operator+ | TAINT | +| string.cpp:144:13:144:14 | s2 | string.cpp:144:11:144:11 | call to operator+ | TAINT | +| string.cpp:145:8:145:9 | s2 | string.cpp:145:11:145:11 | call to operator+ | TAINT | +| string.cpp:145:13:145:14 | s1 | string.cpp:145:11:145:11 | call to operator+ | TAINT | +| string.cpp:146:8:146:9 | s2 | string.cpp:146:11:146:11 | call to operator+ | TAINT | +| string.cpp:146:13:146:14 | s2 | string.cpp:146:11:146:11 | call to operator+ | TAINT | +| string.cpp:148:8:148:9 | s1 | string.cpp:148:11:148:11 | call to operator+ | TAINT | +| string.cpp:148:13:148:20 | world | string.cpp:148:11:148:11 | call to operator+ | TAINT | +| string.cpp:149:8:149:9 | s1 | string.cpp:149:11:149:11 | call to operator+ | TAINT | +| string.cpp:149:13:149:18 | call to source | string.cpp:149:11:149:11 | call to operator+ | TAINT | +| string.cpp:153:18:153:22 | abc | string.cpp:153:18:153:23 | call to basic_string | TAINT | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:157:8:157:9 | s3 | | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:160:8:160:9 | s3 | | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:164:8:164:9 | s3 | | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:169:8:169:9 | s3 | | +| string.cpp:153:18:153:23 | call to basic_string | string.cpp:173:8:173:9 | s3 | | +| string.cpp:154:18:154:23 | call to source | string.cpp:154:18:154:26 | call to basic_string | TAINT | +| string.cpp:154:18:154:26 | call to basic_string | string.cpp:157:13:157:14 | s4 | | +| string.cpp:154:18:154:26 | call to basic_string | string.cpp:161:9:161:10 | s4 | | +| string.cpp:154:18:154:26 | call to basic_string | string.cpp:170:13:170:14 | s4 | | +| string.cpp:157:8:157:9 | s3 | string.cpp:157:11:157:11 | call to operator+ | TAINT | +| string.cpp:157:11:157:11 | call to operator+ | string.cpp:157:3:157:14 | ... = ... | | +| string.cpp:157:11:157:11 | call to operator+ | string.cpp:158:8:158:9 | s5 | | +| string.cpp:157:13:157:14 | s4 | string.cpp:157:11:157:11 | call to operator+ | TAINT | +| string.cpp:160:8:160:9 | s3 | string.cpp:160:3:160:9 | ... = ... | | +| 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 | ... = ... | | +| string.cpp:164:8:164:9 | s3 | string.cpp:165:3:165:4 | s7 | | +| string.cpp:164:8:164:9 | s3 | string.cpp:166:3:166:4 | s7 | | +| 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 | ... = ... | | +| string.cpp:173:8:173:9 | s3 | string.cpp:174:3:174:4 | s9 | | +| string.cpp:173:8:173:9 | s3 | string.cpp:175:3:175:4 | s9 | | +| 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 | +| string.cpp:180:19:180:24 | call to basic_string | string.cpp:183:3:183:5 | s10 | | +| 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 | | +| stringstream.cpp:13:25:13:27 | call to basic_stringstream | stringstream.cpp:17:2:17:4 | ss2 | | +| stringstream.cpp:13:25:13:27 | call to basic_stringstream | stringstream.cpp:23:7:23:9 | ss2 | | +| stringstream.cpp:13:25:13:27 | call to basic_stringstream | stringstream.cpp:28:7:28:9 | ss2 | | +| stringstream.cpp:13:30:13:32 | call to basic_stringstream | stringstream.cpp:18:2:18:4 | ss3 | | +| stringstream.cpp:13:30:13:32 | call to basic_stringstream | stringstream.cpp:24:7:24:9 | ss3 | | +| stringstream.cpp:13:30:13:32 | call to basic_stringstream | stringstream.cpp:29:7:29:9 | ss3 | | +| stringstream.cpp:13:35:13:37 | call to basic_stringstream | stringstream.cpp:19:2:19:4 | ss4 | | +| stringstream.cpp:13:35:13:37 | call to basic_stringstream | stringstream.cpp:25:7:25:9 | ss4 | | +| stringstream.cpp:13:35:13:37 | call to basic_stringstream | stringstream.cpp:30:7:30:9 | ss4 | | +| stringstream.cpp:13:40:13:42 | call to basic_stringstream | stringstream.cpp:20:2:20:4 | ss5 | | +| stringstream.cpp:13:40:13:42 | call to basic_stringstream | stringstream.cpp:26:7:26:9 | ss5 | | +| stringstream.cpp:13:40:13:42 | call to basic_stringstream | stringstream.cpp:31:7:31:9 | ss5 | | +| stringstream.cpp:14:16:14:21 | call to source | stringstream.cpp:14:16:14:24 | call to basic_string | TAINT | +| stringstream.cpp:14:16:14:24 | call to basic_string | stringstream.cpp:20:9:20:9 | t | | +| stringstream.cpp:16:2:16:4 | ref arg ss1 | stringstream.cpp:22:7:22:9 | ss1 | | +| stringstream.cpp:16:2:16:4 | ref arg ss1 | stringstream.cpp:27:7:27:9 | ss1 | | +| stringstream.cpp:17:2:17:4 | ref arg ss2 | stringstream.cpp:23:7:23:9 | ss2 | | +| stringstream.cpp:17:2:17:4 | ref arg ss2 | stringstream.cpp:28:7:28:9 | ss2 | | +| stringstream.cpp:18:2:18:4 | ref arg ss3 | stringstream.cpp:24:7:24:9 | ss3 | | +| stringstream.cpp:18:2:18:4 | ref arg ss3 | stringstream.cpp:29:7:29:9 | ss3 | | +| stringstream.cpp:19:2:19:4 | ref arg ss4 | stringstream.cpp:25:7:25:9 | ss4 | | +| stringstream.cpp:19:2:19:4 | ref arg ss4 | stringstream.cpp:30:7:30:9 | ss4 | | +| stringstream.cpp:20:2:20:4 | ref arg ss5 | stringstream.cpp:26:7:26:9 | ss5 | | +| stringstream.cpp:20:2:20:4 | ref arg ss5 | stringstream.cpp:31:7:31:9 | ss5 | | +| stringstream.cpp:34:32:34:37 | source | stringstream.cpp:39:9:39:14 | source | | +| stringstream.cpp:36:20:36:22 | call to basic_stringstream | stringstream.cpp:38:2:38:4 | ss1 | | +| stringstream.cpp:36:20:36:22 | call to basic_stringstream | stringstream.cpp:41:7:41:9 | ss1 | | +| stringstream.cpp:36:20:36:22 | call to basic_stringstream | stringstream.cpp:43:7:43:9 | ss1 | | +| stringstream.cpp:36:25:36:27 | call to basic_stringstream | stringstream.cpp:39:2:39:4 | ss2 | | +| stringstream.cpp:36:25:36:27 | call to basic_stringstream | stringstream.cpp:42:7:42:9 | ss2 | | +| stringstream.cpp:36:25:36:27 | call to basic_stringstream | stringstream.cpp:44:7:44:9 | ss2 | | +| stringstream.cpp:38:2:38:4 | ref arg ss1 | stringstream.cpp:41:7:41:9 | ss1 | | +| stringstream.cpp:38:2:38:4 | ref arg ss1 | stringstream.cpp:43:7:43:9 | ss1 | | +| stringstream.cpp:39:2:39:4 | ref arg ss2 | stringstream.cpp:42:7:42:9 | ss2 | | +| stringstream.cpp:39:2:39:4 | ref arg ss2 | stringstream.cpp:44:7:44:9 | ss2 | | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | Unknown literal | structlikeclass.cpp:5:7:5:7 | constructor init of field v | TAINT | | structlikeclass.cpp:5:7:5:7 | this | structlikeclass.cpp:5:7:5:7 | constructor init of field v [pre-this] | | @@ -1305,3 +1513,429 @@ | taint.cpp:483:18:483:19 | ref arg & ... | taint.cpp:483:19:483:19 | n [inner post update] | | | taint.cpp:483:19:483:19 | n | taint.cpp:483:18:483:19 | & ... | | | taint.cpp:483:28:483:34 | source1 | taint.cpp:483:11:483:15 | ref arg & ... | TAINT | +| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | | +| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | | +| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | | +| vector.cpp:17:21:17:33 | call to vector | vector.cpp:23:38:23:38 | v | | +| vector.cpp:17:21:17:33 | call to vector | vector.cpp:23:55:23:55 | v | | +| vector.cpp:17:21:17:33 | call to vector | vector.cpp:27:15:27:15 | v | | +| vector.cpp:17:21:17:33 | call to vector | vector.cpp:35:1:35:1 | v | | +| vector.cpp:17:26:17:32 | source1 | vector.cpp:17:21:17:33 | call to vector | TAINT | +| vector.cpp:19:14:19:14 | call to begin | vector.cpp:19:14:19:14 | (__begin) | | +| vector.cpp:19:14:19:14 | call to begin | vector.cpp:19:14:19:14 | (__begin) | | +| vector.cpp:19:14:19:14 | call to begin | vector.cpp:19:14:19:14 | (__begin) | | +| vector.cpp:19:14:19:14 | call to end | vector.cpp:19:14:19:14 | (__end) | | +| vector.cpp:19:14:19:14 | call to operator* | vector.cpp:20:8:20:8 | x | | +| vector.cpp:19:14:19:14 | ref arg (__begin) | vector.cpp:19:14:19:14 | (__begin) | | +| vector.cpp:19:14:19:14 | ref arg (__begin) | vector.cpp:19:14:19:14 | (__begin) | | +| vector.cpp:19:14:19:14 | ref arg (__begin) | vector.cpp:19:14:19:14 | (__begin) | | +| vector.cpp:19:14:19:14 | ref arg (__range) | vector.cpp:19:14:19:14 | (__range) | | +| vector.cpp:19:14:19:14 | v | vector.cpp:19:14:19:14 | (__range) | | +| vector.cpp:19:14:19:14 | v | vector.cpp:19:14:19:14 | (__range) | | +| vector.cpp:19:14:19:14 | v | vector.cpp:19:14:19:14 | call to operator* | TAINT | +| vector.cpp:23:38:23:38 | ref arg v | vector.cpp:23:55:23:55 | v | | +| vector.cpp:23:38:23:38 | ref arg v | vector.cpp:27:15:27:15 | v | | +| vector.cpp:23:38:23:38 | ref arg v | vector.cpp:35:1:35:1 | v | | +| vector.cpp:23:40:23:44 | call to begin | vector.cpp:23:49:23:50 | it | | +| vector.cpp:23:40:23:44 | call to begin | vector.cpp:23:66:23:67 | it | | +| vector.cpp:23:40:23:44 | call to begin | vector.cpp:24:9:24:10 | it | | +| vector.cpp:23:55:23:55 | ref arg v | vector.cpp:23:55:23:55 | v | | +| vector.cpp:23:55:23:55 | ref arg v | vector.cpp:27:15:27:15 | v | | +| vector.cpp:23:55:23:55 | ref arg v | vector.cpp:35:1:35:1 | v | | +| vector.cpp:23:66:23:67 | ref arg it | vector.cpp:23:49:23:50 | it | | +| vector.cpp:23:66:23:67 | ref arg it | vector.cpp:23:66:23:67 | it | | +| vector.cpp:23:66:23:67 | ref arg it | vector.cpp:24:9:24:10 | it | | +| vector.cpp:27:15:27:15 | call to begin | vector.cpp:27:15:27:15 | (__begin) | | +| vector.cpp:27:15:27:15 | call to begin | vector.cpp:27:15:27:15 | (__begin) | | +| vector.cpp:27:15:27:15 | call to begin | vector.cpp:27:15:27:15 | (__begin) | | +| vector.cpp:27:15:27:15 | call to end | vector.cpp:27:15:27:15 | (__end) | | +| vector.cpp:27:15:27:15 | call to operator* | vector.cpp:28:8:28:8 | x | | +| vector.cpp:27:15:27:15 | ref arg (__begin) | vector.cpp:27:15:27:15 | (__begin) | | +| vector.cpp:27:15:27:15 | ref arg (__begin) | vector.cpp:27:15:27:15 | (__begin) | | +| vector.cpp:27:15:27:15 | ref arg (__begin) | vector.cpp:27:15:27:15 | (__begin) | | +| vector.cpp:27:15:27:15 | ref arg (__range) | vector.cpp:27:15:27:15 | (__range) | | +| vector.cpp:27:15:27:15 | v | vector.cpp:27:15:27:15 | (__range) | | +| vector.cpp:27:15:27:15 | v | vector.cpp:27:15:27:15 | (__range) | | +| vector.cpp:27:15:27:15 | v | vector.cpp:27:15:27:15 | call to operator* | TAINT | +| vector.cpp:31:33:31:45 | call to vector | vector.cpp:32:21:32:27 | const_v | | +| vector.cpp:31:33:31:45 | call to vector | vector.cpp:35:1:35:1 | const_v | | +| vector.cpp:31:38:31:44 | source1 | vector.cpp:31:33:31:45 | call to vector | TAINT | +| vector.cpp:32:21:32:21 | call to begin | vector.cpp:32:21:32:21 | (__begin) | | +| vector.cpp:32:21:32:21 | call to begin | vector.cpp:32:21:32:21 | (__begin) | | +| vector.cpp:32:21:32:21 | call to begin | vector.cpp:32:21:32:21 | (__begin) | | +| vector.cpp:32:21:32:21 | call to end | vector.cpp:32:21:32:21 | (__end) | | +| vector.cpp:32:21:32:21 | call to operator* | vector.cpp:33:8:33:8 | x | | +| vector.cpp:32:21:32:21 | ref arg (__begin) | vector.cpp:32:21:32:21 | (__begin) | | +| vector.cpp:32:21:32:21 | ref arg (__begin) | vector.cpp:32:21:32:21 | (__begin) | | +| vector.cpp:32:21:32:21 | ref arg (__begin) | vector.cpp:32:21:32:21 | (__begin) | | +| vector.cpp:32:21:32:27 | const_v | vector.cpp:32:21:32:21 | (__range) | | +| vector.cpp:32:21:32:27 | const_v | vector.cpp:32:21:32:21 | (__range) | | +| vector.cpp:32:21:32:27 | const_v | vector.cpp:32:21:32:21 | call to operator* | TAINT | +| vector.cpp:37:29:37:29 | x | vector.cpp:42:5:42:5 | x | | +| vector.cpp:37:29:37:29 | x | vector.cpp:47:10:47:10 | x | | +| vector.cpp:37:29:37:29 | x | vector.cpp:55:10:55:10 | x | | +| vector.cpp:37:29:37:29 | x | vector.cpp:61:10:61:10 | x | | +| vector.cpp:37:29:37:29 | x | vector.cpp:63:5:63:5 | x | | +| vector.cpp:37:29:37:29 | x | vector.cpp:67:10:67:10 | x | | +| vector.cpp:37:29:37:29 | x | vector.cpp:96:8:96:8 | x | | +| vector.cpp:37:29:37:29 | x | vector.cpp:100:13:100:13 | x | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:40:2:40:3 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:41:2:41:3 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:42:2:42:3 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:43:2:43:3 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:44:7:44:8 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:45:7:45:8 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:46:7:46:8 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:47:7:47:8 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:48:7:48:8 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:38:22:38:24 | call to vector | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:38:30:38:32 | call to vector | vector.cpp:51:2:51:3 | v2 | | +| vector.cpp:38:30:38:32 | call to vector | vector.cpp:52:7:52:8 | v2 | | +| vector.cpp:38:30:38:32 | call to vector | vector.cpp:53:7:53:8 | v2 | | +| vector.cpp:38:30:38:32 | call to vector | vector.cpp:54:7:54:8 | v2 | | +| vector.cpp:38:30:38:32 | call to vector | vector.cpp:55:7:55:8 | v2 | | +| vector.cpp:38:30:38:32 | call to vector | vector.cpp:57:7:57:8 | v2 | | +| vector.cpp:38:30:38:32 | call to vector | vector.cpp:101:1:101:1 | v2 | | +| vector.cpp:38:38:38:40 | call to vector | vector.cpp:57:2:57:3 | v3 | | +| vector.cpp:38:38:38:40 | call to vector | vector.cpp:58:7:58:8 | v3 | | +| vector.cpp:38:38:38:40 | call to vector | vector.cpp:59:7:59:8 | v3 | | +| vector.cpp:38:38:38:40 | call to vector | vector.cpp:60:7:60:8 | v3 | | +| vector.cpp:38:38:38:40 | call to vector | vector.cpp:61:7:61:8 | v3 | | +| vector.cpp:38:38:38:40 | call to vector | vector.cpp:101:1:101:1 | v3 | | +| vector.cpp:38:46:38:48 | call to vector | vector.cpp:63:2:63:3 | v4 | | +| vector.cpp:38:46:38:48 | call to vector | vector.cpp:64:7:64:8 | v4 | | +| vector.cpp:38:46:38:48 | call to vector | vector.cpp:65:7:65:8 | v4 | | +| vector.cpp:38:46:38:48 | call to vector | vector.cpp:66:7:66:8 | v4 | | +| vector.cpp:38:46:38:48 | call to vector | vector.cpp:67:7:67:8 | v4 | | +| vector.cpp:38:46:38:48 | call to vector | vector.cpp:101:1:101:1 | v4 | | +| vector.cpp:38:54:38:56 | call to vector | vector.cpp:69:2:69:3 | v5 | | +| vector.cpp:38:54:38:56 | call to vector | vector.cpp:70:7:70:8 | v5 | | +| vector.cpp:38:54:38:56 | call to vector | vector.cpp:71:7:71:8 | v5 | | +| vector.cpp:38:54:38:56 | call to vector | vector.cpp:72:7:72:8 | v5 | | +| vector.cpp:38:54:38:56 | call to vector | vector.cpp:101:1:101:1 | v5 | | +| vector.cpp:38:62:38:64 | call to vector | vector.cpp:74:2:74:3 | v6 | | +| vector.cpp:38:62:38:64 | call to vector | vector.cpp:75:7:75:8 | v6 | | +| vector.cpp:38:62:38:64 | call to vector | vector.cpp:76:7:76:8 | v6 | | +| vector.cpp:38:62:38:64 | call to vector | vector.cpp:101:1:101:1 | v6 | | +| vector.cpp:38:70:38:72 | call to vector | vector.cpp:79:33:79:34 | v7 | | +| vector.cpp:38:70:38:72 | call to vector | vector.cpp:81:3:81:4 | v7 | | +| vector.cpp:38:70:38:72 | call to vector | vector.cpp:83:7:83:8 | v7 | | +| vector.cpp:38:70:38:72 | call to vector | vector.cpp:84:7:84:8 | v7 | | +| vector.cpp:38:70:38:72 | call to vector | vector.cpp:85:7:85:8 | v7 | | +| vector.cpp:38:70:38:72 | call to vector | vector.cpp:101:1:101:1 | v7 | | +| vector.cpp:38:78:38:80 | call to vector | vector.cpp:88:33:88:34 | v8 | | +| vector.cpp:38:78:38:80 | call to vector | vector.cpp:90:3:90:4 | v8 | | +| vector.cpp:38:78:38:80 | call to vector | vector.cpp:92:7:92:8 | v8 | | +| vector.cpp:38:78:38:80 | call to vector | vector.cpp:93:7:93:8 | v8 | | +| vector.cpp:38:78:38:80 | call to vector | vector.cpp:94:7:94:8 | v8 | | +| vector.cpp:38:78:38:80 | call to vector | vector.cpp:101:1:101:1 | v8 | | +| vector.cpp:38:86:38:88 | call to vector | vector.cpp:96:2:96:3 | v9 | | +| vector.cpp:38:86:38:88 | call to vector | vector.cpp:97:7:97:8 | v9 | | +| vector.cpp:38:86:38:88 | call to vector | vector.cpp:98:7:98:8 | v9 | | +| vector.cpp:38:86:38:88 | call to vector | vector.cpp:99:7:99:8 | v9 | | +| vector.cpp:38:86:38:88 | call to vector | vector.cpp:100:7:100:8 | v9 | | +| vector.cpp:38:86:38:88 | call to vector | vector.cpp:101:1:101:1 | v9 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:41:2:41:3 | v1 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:42:2:42:3 | v1 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:43:2:43:3 | v1 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:44:7:44:8 | v1 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:45:7:45:8 | v1 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:46:7:46:8 | v1 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:47:7:47:8 | v1 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:48:7:48:8 | v1 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:40:2:40:3 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:40:10:40:10 | 0 | vector.cpp:40:2:40:10 | ... = ... | | +| vector.cpp:41:2:41:3 | ref arg v1 | vector.cpp:42:2:42:3 | v1 | | +| vector.cpp:41:2:41:3 | ref arg v1 | vector.cpp:43:2:43:3 | v1 | | +| vector.cpp:41:2:41:3 | ref arg v1 | vector.cpp:44:7:44:8 | v1 | | +| vector.cpp:41:2:41:3 | ref arg v1 | vector.cpp:45:7:45:8 | v1 | | +| vector.cpp:41:2:41:3 | ref arg v1 | vector.cpp:46:7:46:8 | v1 | | +| vector.cpp:41:2:41:3 | ref arg v1 | vector.cpp:47:7:47:8 | v1 | | +| vector.cpp:41:2:41:3 | ref arg v1 | vector.cpp:48:7:48:8 | v1 | | +| vector.cpp:41:2:41:3 | ref arg v1 | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:41:2:41:3 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:41:10:41:10 | 0 | vector.cpp:41:2:41:10 | ... = ... | | +| vector.cpp:42:2:42:3 | ref arg v1 | vector.cpp:43:2:43:3 | v1 | | +| vector.cpp:42:2:42:3 | ref arg v1 | vector.cpp:44:7:44:8 | v1 | | +| vector.cpp:42:2:42:3 | ref arg v1 | vector.cpp:45:7:45:8 | v1 | | +| vector.cpp:42:2:42:3 | ref arg v1 | vector.cpp:46:7:46:8 | v1 | | +| vector.cpp:42:2:42:3 | ref arg v1 | vector.cpp:47:7:47:8 | v1 | | +| vector.cpp:42:2:42:3 | ref arg v1 | vector.cpp:48:7:48:8 | v1 | | +| vector.cpp:42:2:42:3 | ref arg v1 | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:42:2:42:3 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:42:10:42:10 | 0 | vector.cpp:42:2:42:10 | ... = ... | | +| vector.cpp:43:2:43:3 | ref arg v1 | vector.cpp:44:7:44:8 | v1 | | +| vector.cpp:43:2:43:3 | ref arg v1 | vector.cpp:45:7:45:8 | v1 | | +| vector.cpp:43:2:43:3 | ref arg v1 | vector.cpp:46:7:46:8 | v1 | | +| vector.cpp:43:2:43:3 | ref arg v1 | vector.cpp:47:7:47:8 | v1 | | +| vector.cpp:43:2:43:3 | ref arg v1 | vector.cpp:48:7:48:8 | v1 | | +| vector.cpp:43:2:43:3 | ref arg v1 | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:43:2:43:3 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:43:15:43:15 | 1 | vector.cpp:43:2:43:3 | ref arg v1 | TAINT | +| vector.cpp:44:7:44:8 | ref arg v1 | vector.cpp:45:7:45:8 | v1 | | +| vector.cpp:44:7:44:8 | ref arg v1 | vector.cpp:46:7:46:8 | v1 | | +| vector.cpp:44:7:44:8 | ref arg v1 | vector.cpp:47:7:47:8 | v1 | | +| vector.cpp:44:7:44:8 | ref arg v1 | vector.cpp:48:7:48:8 | v1 | | +| vector.cpp:44:7:44:8 | ref arg v1 | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:44:7:44:8 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:45:7:45:8 | ref arg v1 | vector.cpp:46:7:46:8 | v1 | | +| vector.cpp:45:7:45:8 | ref arg v1 | vector.cpp:47:7:47:8 | v1 | | +| vector.cpp:45:7:45:8 | ref arg v1 | vector.cpp:48:7:48:8 | v1 | | +| vector.cpp:45:7:45:8 | ref arg v1 | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:45:7:45:8 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:46:7:46:8 | ref arg v1 | vector.cpp:47:7:47:8 | v1 | | +| vector.cpp:46:7:46:8 | ref arg v1 | vector.cpp:48:7:48:8 | v1 | | +| vector.cpp:46:7:46:8 | ref arg v1 | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:46:7:46:8 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:47:7:47:8 | ref arg v1 | vector.cpp:48:7:48:8 | v1 | | +| vector.cpp:47:7:47:8 | ref arg v1 | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:47:7:47:8 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:48:7:48:8 | ref arg v1 | vector.cpp:49:7:49:8 | v1 | | +| vector.cpp:48:7:48:8 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:48:7:48:8 | v1 | vector.cpp:48:10:48:14 | call to front | TAINT | +| vector.cpp:49:7:49:8 | ref arg v1 | vector.cpp:101:1:101:1 | v1 | | +| vector.cpp:49:7:49:8 | v1 | vector.cpp:49:10:49:13 | call to back | TAINT | +| vector.cpp:51:2:51:3 | ref arg v2 | vector.cpp:52:7:52:8 | v2 | | +| vector.cpp:51:2:51:3 | ref arg v2 | vector.cpp:53:7:53:8 | v2 | | +| vector.cpp:51:2:51:3 | ref arg v2 | vector.cpp:54:7:54:8 | v2 | | +| vector.cpp:51:2:51:3 | ref arg v2 | vector.cpp:55:7:55:8 | v2 | | +| vector.cpp:51:2:51:3 | ref arg v2 | vector.cpp:57:7:57:8 | v2 | | +| vector.cpp:51:2:51:3 | ref arg v2 | vector.cpp:101:1:101:1 | v2 | | +| vector.cpp:51:10:51:15 | call to source | vector.cpp:51:2:51:17 | ... = ... | | +| vector.cpp:52:7:52:8 | ref arg v2 | vector.cpp:53:7:53:8 | v2 | | +| vector.cpp:52:7:52:8 | ref arg v2 | vector.cpp:54:7:54:8 | v2 | | +| vector.cpp:52:7:52:8 | ref arg v2 | vector.cpp:55:7:55:8 | v2 | | +| vector.cpp:52:7:52:8 | ref arg v2 | vector.cpp:57:7:57:8 | v2 | | +| vector.cpp:52:7:52:8 | ref arg v2 | vector.cpp:101:1:101:1 | v2 | | +| vector.cpp:53:7:53:8 | ref arg v2 | vector.cpp:54:7:54:8 | v2 | | +| vector.cpp:53:7:53:8 | ref arg v2 | vector.cpp:55:7:55:8 | v2 | | +| vector.cpp:53:7:53:8 | ref arg v2 | vector.cpp:57:7:57:8 | v2 | | +| vector.cpp:53:7:53:8 | ref arg v2 | vector.cpp:101:1:101:1 | v2 | | +| vector.cpp:54:7:54:8 | ref arg v2 | vector.cpp:55:7:55:8 | v2 | | +| vector.cpp:54:7:54:8 | ref arg v2 | vector.cpp:57:7:57:8 | v2 | | +| vector.cpp:54:7:54:8 | ref arg v2 | vector.cpp:101:1:101:1 | v2 | | +| vector.cpp:55:7:55:8 | ref arg v2 | vector.cpp:57:7:57:8 | v2 | | +| vector.cpp:55:7:55:8 | ref arg v2 | vector.cpp:101:1:101:1 | v2 | | +| vector.cpp:57:2:57:3 | ref arg v3 | vector.cpp:58:7:58:8 | v3 | | +| vector.cpp:57:2:57:3 | ref arg v3 | vector.cpp:59:7:59:8 | v3 | | +| vector.cpp:57:2:57:3 | ref arg v3 | vector.cpp:60:7:60:8 | v3 | | +| vector.cpp:57:2:57:3 | ref arg v3 | vector.cpp:61:7:61:8 | v3 | | +| vector.cpp:57:2:57:3 | ref arg v3 | vector.cpp:101:1:101:1 | v3 | | +| vector.cpp:57:7:57:8 | v2 | vector.cpp:57:2:57:3 | ref arg v3 | TAINT | +| vector.cpp:57:7:57:8 | v2 | vector.cpp:57:5:57:5 | call to operator= | TAINT | +| vector.cpp:58:7:58:8 | ref arg v3 | vector.cpp:59:7:59:8 | v3 | | +| vector.cpp:58:7:58:8 | ref arg v3 | vector.cpp:60:7:60:8 | v3 | | +| vector.cpp:58:7:58:8 | ref arg v3 | vector.cpp:61:7:61:8 | v3 | | +| vector.cpp:58:7:58:8 | ref arg v3 | vector.cpp:101:1:101:1 | v3 | | +| vector.cpp:59:7:59:8 | ref arg v3 | vector.cpp:60:7:60:8 | v3 | | +| vector.cpp:59:7:59:8 | ref arg v3 | vector.cpp:61:7:61:8 | v3 | | +| vector.cpp:59:7:59:8 | ref arg v3 | vector.cpp:101:1:101:1 | v3 | | +| vector.cpp:60:7:60:8 | ref arg v3 | vector.cpp:61:7:61:8 | v3 | | +| vector.cpp:60:7:60:8 | ref arg v3 | vector.cpp:101:1:101:1 | v3 | | +| vector.cpp:61:7:61:8 | ref arg v3 | vector.cpp:101:1:101:1 | v3 | | +| vector.cpp:63:2:63:3 | ref arg v4 | vector.cpp:64:7:64:8 | v4 | | +| vector.cpp:63:2:63:3 | ref arg v4 | vector.cpp:65:7:65:8 | v4 | | +| vector.cpp:63:2:63:3 | ref arg v4 | vector.cpp:66:7:66:8 | v4 | | +| vector.cpp:63:2:63:3 | ref arg v4 | vector.cpp:67:7:67:8 | v4 | | +| vector.cpp:63:2:63:3 | ref arg v4 | vector.cpp:101:1:101:1 | v4 | | +| vector.cpp:63:10:63:15 | call to source | vector.cpp:63:2:63:17 | ... = ... | | +| vector.cpp:64:7:64:8 | ref arg v4 | vector.cpp:65:7:65:8 | v4 | | +| vector.cpp:64:7:64:8 | ref arg v4 | vector.cpp:66:7:66:8 | v4 | | +| vector.cpp:64:7:64:8 | ref arg v4 | vector.cpp:67:7:67:8 | v4 | | +| vector.cpp:64:7:64:8 | ref arg v4 | vector.cpp:101:1:101:1 | v4 | | +| vector.cpp:65:7:65:8 | ref arg v4 | vector.cpp:66:7:66:8 | v4 | | +| vector.cpp:65:7:65:8 | ref arg v4 | vector.cpp:67:7:67:8 | v4 | | +| vector.cpp:65:7:65:8 | ref arg v4 | vector.cpp:101:1:101:1 | v4 | | +| vector.cpp:66:7:66:8 | ref arg v4 | vector.cpp:67:7:67:8 | v4 | | +| vector.cpp:66:7:66:8 | ref arg v4 | vector.cpp:101:1:101:1 | v4 | | +| vector.cpp:67:7:67:8 | ref arg v4 | vector.cpp:101:1:101:1 | v4 | | +| vector.cpp:69:2:69:3 | ref arg v5 | vector.cpp:70:7:70:8 | v5 | | +| vector.cpp:69:2:69:3 | ref arg v5 | vector.cpp:71:7:71:8 | v5 | | +| vector.cpp:69:2:69:3 | ref arg v5 | vector.cpp:72:7:72:8 | v5 | | +| vector.cpp:69:2:69:3 | ref arg v5 | vector.cpp:101:1:101:1 | v5 | | +| vector.cpp:69:15:69:20 | call to source | vector.cpp:69:2:69:3 | ref arg v5 | TAINT | +| vector.cpp:70:7:70:8 | ref arg v5 | vector.cpp:71:7:71:8 | v5 | | +| vector.cpp:70:7:70:8 | ref arg v5 | vector.cpp:72:7:72:8 | v5 | | +| vector.cpp:70:7:70:8 | ref arg v5 | vector.cpp:101:1:101:1 | v5 | | +| vector.cpp:71:7:71:8 | ref arg v5 | vector.cpp:72:7:72:8 | v5 | | +| vector.cpp:71:7:71:8 | ref arg v5 | vector.cpp:101:1:101:1 | v5 | | +| vector.cpp:71:7:71:8 | v5 | vector.cpp:71:10:71:14 | call to front | TAINT | +| vector.cpp:72:7:72:8 | ref arg v5 | vector.cpp:101:1:101:1 | v5 | | +| vector.cpp:72:7:72:8 | v5 | vector.cpp:72:10:72:13 | call to back | TAINT | +| vector.cpp:74:2:74:3 | ref arg v6 | vector.cpp:75:7:75:8 | v6 | | +| vector.cpp:74:2:74:3 | ref arg v6 | vector.cpp:76:7:76:8 | v6 | | +| vector.cpp:74:2:74:3 | ref arg v6 | vector.cpp:101:1:101:1 | v6 | | +| vector.cpp:74:2:74:13 | access to array [post update] | vector.cpp:74:5:74:8 | call to data [inner post update] | | +| vector.cpp:74:5:74:8 | call to data | vector.cpp:74:2:74:13 | access to array | TAINT | +| vector.cpp:74:12:74:12 | 2 | vector.cpp:74:2:74:13 | access to array | TAINT | +| vector.cpp:74:17:74:22 | call to source | vector.cpp:74:2:74:24 | ... = ... | | +| vector.cpp:75:7:75:8 | ref arg v6 | vector.cpp:76:7:76:8 | v6 | | +| vector.cpp:75:7:75:8 | ref arg v6 | vector.cpp:101:1:101:1 | v6 | | +| vector.cpp:76:7:76:8 | ref arg v6 | vector.cpp:101:1:101:1 | v6 | | +| vector.cpp:76:10:76:13 | call to data | vector.cpp:76:7:76:18 | access to array | TAINT | +| vector.cpp:76:17:76:17 | 2 | vector.cpp:76:7:76:18 | access to array | TAINT | +| vector.cpp:79:33:79:34 | v7 | vector.cpp:80:41:80:43 | v7c | | +| vector.cpp:80:45:80:49 | call to begin | vector.cpp:81:13:81:14 | it | | +| vector.cpp:81:3:81:4 | ref arg v7 | vector.cpp:83:7:83:8 | v7 | | +| vector.cpp:81:3:81:4 | ref arg v7 | vector.cpp:84:7:84:8 | v7 | | +| vector.cpp:81:3:81:4 | ref arg v7 | vector.cpp:85:7:85:8 | v7 | | +| vector.cpp:81:3:81:4 | ref arg v7 | vector.cpp:101:1:101:1 | v7 | | +| vector.cpp:83:7:83:8 | ref arg v7 | vector.cpp:84:7:84:8 | v7 | | +| vector.cpp:83:7:83:8 | ref arg v7 | vector.cpp:85:7:85:8 | v7 | | +| vector.cpp:83:7:83:8 | ref arg v7 | vector.cpp:101:1:101:1 | v7 | | +| vector.cpp:84:7:84:8 | ref arg v7 | vector.cpp:85:7:85:8 | v7 | | +| vector.cpp:84:7:84:8 | ref arg v7 | vector.cpp:101:1:101:1 | v7 | | +| vector.cpp:84:7:84:8 | v7 | vector.cpp:84:10:84:14 | call to front | TAINT | +| vector.cpp:85:7:85:8 | ref arg v7 | vector.cpp:101:1:101:1 | v7 | | +| vector.cpp:85:7:85:8 | v7 | vector.cpp:85:10:85:13 | call to back | TAINT | +| vector.cpp:88:33:88:34 | v8 | vector.cpp:89:41:89:43 | v8c | | +| vector.cpp:89:45:89:49 | call to begin | vector.cpp:90:13:90:14 | it | | +| vector.cpp:90:3:90:4 | ref arg v8 | vector.cpp:92:7:92:8 | v8 | | +| vector.cpp:90:3:90:4 | ref arg v8 | vector.cpp:93:7:93:8 | v8 | | +| vector.cpp:90:3:90:4 | ref arg v8 | vector.cpp:94:7:94:8 | v8 | | +| vector.cpp:90:3:90:4 | ref arg v8 | vector.cpp:101:1:101:1 | v8 | | +| vector.cpp:92:7:92:8 | ref arg v8 | vector.cpp:93:7:93:8 | v8 | | +| vector.cpp:92:7:92:8 | ref arg v8 | vector.cpp:94:7:94:8 | v8 | | +| vector.cpp:92:7:92:8 | ref arg v8 | vector.cpp:101:1:101:1 | v8 | | +| vector.cpp:93:7:93:8 | ref arg v8 | vector.cpp:94:7:94:8 | v8 | | +| vector.cpp:93:7:93:8 | ref arg v8 | vector.cpp:101:1:101:1 | v8 | | +| vector.cpp:93:7:93:8 | v8 | vector.cpp:93:10:93:14 | call to front | TAINT | +| vector.cpp:94:7:94:8 | ref arg v8 | vector.cpp:101:1:101:1 | v8 | | +| vector.cpp:94:7:94:8 | v8 | vector.cpp:94:10:94:13 | call to back | TAINT | +| vector.cpp:96:2:96:3 | ref arg v9 | vector.cpp:97:7:97:8 | v9 | | +| vector.cpp:96:2:96:3 | ref arg v9 | vector.cpp:98:7:98:8 | v9 | | +| vector.cpp:96:2:96:3 | ref arg v9 | vector.cpp:99:7:99:8 | v9 | | +| vector.cpp:96:2:96:3 | ref arg v9 | vector.cpp:100:7:100:8 | v9 | | +| vector.cpp:96:2:96:3 | ref arg v9 | vector.cpp:101:1:101:1 | v9 | | +| vector.cpp:96:13:96:18 | call to source | vector.cpp:96:2:96:20 | ... = ... | | +| vector.cpp:97:7:97:8 | ref arg v9 | vector.cpp:98:7:98:8 | v9 | | +| vector.cpp:97:7:97:8 | ref arg v9 | vector.cpp:99:7:99:8 | v9 | | +| vector.cpp:97:7:97:8 | ref arg v9 | vector.cpp:100:7:100:8 | v9 | | +| vector.cpp:97:7:97:8 | ref arg v9 | vector.cpp:101:1:101:1 | v9 | | +| vector.cpp:98:7:98:8 | ref arg v9 | vector.cpp:99:7:99:8 | v9 | | +| vector.cpp:98:7:98:8 | ref arg v9 | vector.cpp:100:7:100:8 | v9 | | +| vector.cpp:98:7:98:8 | ref arg v9 | vector.cpp:101:1:101:1 | v9 | | +| vector.cpp:99:7:99:8 | ref arg v9 | vector.cpp:100:7:100:8 | v9 | | +| vector.cpp:99:7:99:8 | ref arg v9 | vector.cpp:101:1:101:1 | v9 | | +| vector.cpp:100:7:100:8 | ref arg v9 | vector.cpp:101:1:101:1 | v9 | | +| vector.cpp:104:22:104:24 | call to vector | vector.cpp:106:2:106:3 | v1 | | +| vector.cpp:104:22:104:24 | call to vector | vector.cpp:109:7:109:8 | v1 | | +| vector.cpp:104:22:104:24 | call to vector | vector.cpp:114:2:114:3 | v1 | | +| vector.cpp:104:22:104:24 | call to vector | vector.cpp:117:7:117:8 | v1 | | +| vector.cpp:104:22:104:24 | call to vector | vector.cpp:121:1:121:1 | v1 | | +| vector.cpp:104:30:104:32 | call to vector | vector.cpp:110:7:110:8 | v2 | | +| vector.cpp:104:30:104:32 | call to vector | vector.cpp:114:10:114:11 | v2 | | +| vector.cpp:104:30:104:32 | call to vector | vector.cpp:118:7:118:8 | v2 | | +| vector.cpp:104:30:104:32 | call to vector | vector.cpp:121:1:121:1 | v2 | | +| vector.cpp:104:38:104:40 | call to vector | vector.cpp:111:7:111:8 | v3 | | +| vector.cpp:104:38:104:40 | call to vector | vector.cpp:115:2:115:3 | v3 | | +| vector.cpp:104:38:104:40 | call to vector | vector.cpp:119:7:119:8 | v3 | | +| vector.cpp:104:38:104:40 | call to vector | vector.cpp:121:1:121:1 | v3 | | +| vector.cpp:104:46:104:48 | call to vector | vector.cpp:107:2:107:3 | v4 | | +| vector.cpp:104:46:104:48 | call to vector | vector.cpp:112:7:112:8 | v4 | | +| vector.cpp:104:46:104:48 | call to vector | vector.cpp:115:10:115:11 | v4 | | +| vector.cpp:104:46:104:48 | call to vector | vector.cpp:120:7:120:8 | v4 | | +| vector.cpp:104:46:104:48 | call to vector | vector.cpp:121:1:121:1 | v4 | | +| vector.cpp:106:2:106:3 | ref arg v1 | vector.cpp:109:7:109:8 | v1 | | +| vector.cpp:106:2:106:3 | ref arg v1 | vector.cpp:114:2:114:3 | v1 | | +| vector.cpp:106:2:106:3 | ref arg v1 | vector.cpp:117:7:117:8 | v1 | | +| vector.cpp:106:2:106:3 | ref arg v1 | vector.cpp:121:1:121:1 | v1 | | +| vector.cpp:106:15:106:20 | call to source | vector.cpp:106:2:106:3 | ref arg v1 | TAINT | +| vector.cpp:107:2:107:3 | ref arg v4 | vector.cpp:112:7:112:8 | v4 | | +| vector.cpp:107:2:107:3 | ref arg v4 | vector.cpp:115:10:115:11 | v4 | | +| vector.cpp:107:2:107:3 | ref arg v4 | vector.cpp:120:7:120:8 | v4 | | +| vector.cpp:107:2:107:3 | ref arg v4 | vector.cpp:121:1:121:1 | v4 | | +| vector.cpp:107:15:107:20 | call to source | vector.cpp:107:2:107:3 | ref arg v4 | TAINT | +| vector.cpp:109:7:109:8 | ref arg v1 | vector.cpp:114:2:114:3 | v1 | | +| vector.cpp:109:7:109:8 | ref arg v1 | vector.cpp:117:7:117:8 | v1 | | +| vector.cpp:109:7:109:8 | ref arg v1 | vector.cpp:121:1:121:1 | v1 | | +| vector.cpp:110:7:110:8 | ref arg v2 | vector.cpp:114:10:114:11 | v2 | | +| vector.cpp:110:7:110:8 | ref arg v2 | vector.cpp:118:7:118:8 | v2 | | +| vector.cpp:110:7:110:8 | ref arg v2 | vector.cpp:121:1:121:1 | v2 | | +| vector.cpp:111:7:111:8 | ref arg v3 | vector.cpp:115:2:115:3 | v3 | | +| vector.cpp:111:7:111:8 | ref arg v3 | vector.cpp:119:7:119:8 | v3 | | +| vector.cpp:111:7:111:8 | ref arg v3 | vector.cpp:121:1:121:1 | v3 | | +| vector.cpp:112:7:112:8 | ref arg v4 | vector.cpp:115:10:115:11 | v4 | | +| vector.cpp:112:7:112:8 | ref arg v4 | vector.cpp:120:7:120:8 | v4 | | +| vector.cpp:112:7:112:8 | ref arg v4 | vector.cpp:121:1:121:1 | v4 | | +| vector.cpp:114:2:114:3 | ref arg v1 | vector.cpp:117:7:117:8 | v1 | | +| vector.cpp:114:2:114:3 | ref arg v1 | vector.cpp:121:1:121:1 | v1 | | +| vector.cpp:114:2:114:3 | v1 | vector.cpp:114:10:114:11 | ref arg v2 | TAINT | +| vector.cpp:114:10:114:11 | ref arg v2 | vector.cpp:118:7:118:8 | v2 | | +| vector.cpp:114:10:114:11 | ref arg v2 | vector.cpp:121:1:121:1 | v2 | | +| vector.cpp:114:10:114:11 | v2 | vector.cpp:114:2:114:3 | ref arg v1 | TAINT | +| vector.cpp:115:2:115:3 | ref arg v3 | vector.cpp:119:7:119:8 | v3 | | +| vector.cpp:115:2:115:3 | ref arg v3 | vector.cpp:121:1:121:1 | v3 | | +| vector.cpp:115:2:115:3 | v3 | vector.cpp:115:10:115:11 | ref arg v4 | TAINT | +| vector.cpp:115:10:115:11 | ref arg v4 | vector.cpp:120:7:120:8 | v4 | | +| vector.cpp:115:10:115:11 | ref arg v4 | vector.cpp:121:1:121:1 | v4 | | +| vector.cpp:115:10:115:11 | v4 | vector.cpp:115:2:115:3 | ref arg v3 | TAINT | +| vector.cpp:117:7:117:8 | ref arg v1 | vector.cpp:121:1:121:1 | v1 | | +| vector.cpp:118:7:118:8 | ref arg v2 | vector.cpp:121:1:121:1 | v2 | | +| vector.cpp:119:7:119:8 | ref arg v3 | vector.cpp:121:1:121:1 | v3 | | +| vector.cpp:120:7:120:8 | ref arg v4 | vector.cpp:121:1:121:1 | v4 | | +| vector.cpp:124:22:124:24 | call to vector | vector.cpp:126:2:126:3 | v1 | | +| vector.cpp:124:22:124:24 | call to vector | vector.cpp:130:7:130:8 | v1 | | +| vector.cpp:124:22:124:24 | call to vector | vector.cpp:135:2:135:3 | v1 | | +| vector.cpp:124:22:124:24 | call to vector | vector.cpp:139:7:139:8 | v1 | | +| vector.cpp:124:22:124:24 | call to vector | vector.cpp:143:1:143:1 | v1 | | +| vector.cpp:124:30:124:32 | call to vector | vector.cpp:127:2:127:3 | v2 | | +| vector.cpp:124:30:124:32 | call to vector | vector.cpp:131:7:131:8 | v2 | | +| vector.cpp:124:30:124:32 | call to vector | vector.cpp:136:2:136:3 | v2 | | +| vector.cpp:124:30:124:32 | call to vector | vector.cpp:136:7:136:8 | v2 | | +| vector.cpp:124:30:124:32 | call to vector | vector.cpp:140:7:140:8 | v2 | | +| vector.cpp:124:30:124:32 | call to vector | vector.cpp:143:1:143:1 | v2 | | +| vector.cpp:124:38:124:40 | call to vector | vector.cpp:128:2:128:3 | v3 | | +| vector.cpp:124:38:124:40 | call to vector | vector.cpp:132:7:132:8 | v3 | | +| vector.cpp:124:38:124:40 | call to vector | vector.cpp:137:2:137:3 | v3 | | +| vector.cpp:124:38:124:40 | call to vector | vector.cpp:141:7:141:8 | v3 | | +| vector.cpp:124:38:124:40 | call to vector | vector.cpp:143:1:143:1 | v3 | | +| vector.cpp:124:46:124:48 | call to vector | vector.cpp:133:7:133:8 | v4 | | +| vector.cpp:124:46:124:48 | call to vector | vector.cpp:137:7:137:8 | v4 | | +| vector.cpp:124:46:124:48 | call to vector | vector.cpp:142:7:142:8 | v4 | | +| vector.cpp:124:46:124:48 | call to vector | vector.cpp:143:1:143:1 | v4 | | +| vector.cpp:126:2:126:3 | ref arg v1 | vector.cpp:130:7:130:8 | v1 | | +| vector.cpp:126:2:126:3 | ref arg v1 | vector.cpp:135:2:135:3 | v1 | | +| vector.cpp:126:2:126:3 | ref arg v1 | vector.cpp:139:7:139:8 | v1 | | +| vector.cpp:126:2:126:3 | ref arg v1 | vector.cpp:143:1:143:1 | v1 | | +| vector.cpp:126:15:126:20 | call to source | vector.cpp:126:2:126:3 | ref arg v1 | TAINT | +| vector.cpp:127:2:127:3 | ref arg v2 | vector.cpp:131:7:131:8 | v2 | | +| vector.cpp:127:2:127:3 | ref arg v2 | vector.cpp:136:2:136:3 | v2 | | +| vector.cpp:127:2:127:3 | ref arg v2 | vector.cpp:136:7:136:8 | v2 | | +| vector.cpp:127:2:127:3 | ref arg v2 | vector.cpp:140:7:140:8 | v2 | | +| vector.cpp:127:2:127:3 | ref arg v2 | vector.cpp:143:1:143:1 | v2 | | +| vector.cpp:127:15:127:20 | call to source | vector.cpp:127:2:127:3 | ref arg v2 | TAINT | +| vector.cpp:128:2:128:3 | ref arg v3 | vector.cpp:132:7:132:8 | v3 | | +| vector.cpp:128:2:128:3 | ref arg v3 | vector.cpp:137:2:137:3 | v3 | | +| vector.cpp:128:2:128:3 | ref arg v3 | vector.cpp:141:7:141:8 | v3 | | +| vector.cpp:128:2:128:3 | ref arg v3 | vector.cpp:143:1:143:1 | v3 | | +| vector.cpp:128:15:128:20 | call to source | vector.cpp:128:2:128:3 | ref arg v3 | TAINT | +| vector.cpp:130:7:130:8 | ref arg v1 | vector.cpp:135:2:135:3 | v1 | | +| vector.cpp:130:7:130:8 | ref arg v1 | vector.cpp:139:7:139:8 | v1 | | +| vector.cpp:130:7:130:8 | ref arg v1 | vector.cpp:143:1:143:1 | v1 | | +| vector.cpp:131:7:131:8 | ref arg v2 | vector.cpp:136:2:136:3 | v2 | | +| vector.cpp:131:7:131:8 | ref arg v2 | vector.cpp:136:7:136:8 | v2 | | +| vector.cpp:131:7:131:8 | ref arg v2 | vector.cpp:140:7:140:8 | v2 | | +| vector.cpp:131:7:131:8 | ref arg v2 | vector.cpp:143:1:143:1 | v2 | | +| vector.cpp:132:7:132:8 | ref arg v3 | vector.cpp:137:2:137:3 | v3 | | +| vector.cpp:132:7:132:8 | ref arg v3 | vector.cpp:141:7:141:8 | v3 | | +| vector.cpp:132:7:132:8 | ref arg v3 | vector.cpp:143:1:143:1 | v3 | | +| vector.cpp:133:7:133:8 | ref arg v4 | vector.cpp:137:7:137:8 | v4 | | +| vector.cpp:133:7:133:8 | ref arg v4 | vector.cpp:142:7:142:8 | v4 | | +| vector.cpp:133:7:133:8 | ref arg v4 | vector.cpp:143:1:143:1 | v4 | | +| vector.cpp:135:2:135:3 | ref arg v1 | vector.cpp:139:7:139:8 | v1 | | +| vector.cpp:135:2:135:3 | ref arg v1 | vector.cpp:143:1:143:1 | v1 | | +| vector.cpp:136:2:136:3 | ref arg v2 | vector.cpp:140:7:140:8 | v2 | | +| vector.cpp:136:2:136:3 | ref arg v2 | vector.cpp:143:1:143:1 | v2 | | +| vector.cpp:136:7:136:8 | v2 | vector.cpp:136:2:136:3 | ref arg v2 | TAINT | +| vector.cpp:136:7:136:8 | v2 | vector.cpp:136:5:136:5 | call to operator= | TAINT | +| vector.cpp:137:2:137:3 | ref arg v3 | vector.cpp:141:7:141:8 | v3 | | +| vector.cpp:137:2:137:3 | ref arg v3 | vector.cpp:143:1:143:1 | v3 | | +| vector.cpp:137:7:137:8 | v4 | vector.cpp:137:2:137:3 | ref arg v3 | TAINT | +| vector.cpp:137:7:137:8 | v4 | vector.cpp:137:5:137:5 | call to operator= | TAINT | +| vector.cpp:139:7:139:8 | ref arg v1 | vector.cpp:143:1:143:1 | v1 | | +| vector.cpp:140:7:140:8 | ref arg v2 | vector.cpp:143:1:143:1 | v2 | | +| vector.cpp:141:7:141:8 | ref arg v3 | vector.cpp:143:1:143:1 | v3 | | +| vector.cpp:142:7:142:8 | ref arg v4 | vector.cpp:143:1:143:1 | v4 | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp deleted file mode 100644 index 654628a4dd4..00000000000 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp +++ /dev/null @@ -1,310 +0,0 @@ - -typedef unsigned long size_t; - -namespace std -{ - template struct char_traits; - - typedef size_t streamsize; - - struct ptrdiff_t; - - template - struct iterator { - iterator &operator++(); - iterator operator++(int); - bool operator==(iterator other) const; - bool operator!=(iterator other) const; - reference_type operator*() const; - }; - - struct input_iterator_tag {}; - struct forward_iterator_tag : public input_iterator_tag {}; - struct bidirectional_iterator_tag : public forward_iterator_tag {}; - struct random_access_iterator_tag : public bidirectional_iterator_tag {}; - - template class allocator { - public: - allocator() throw(); - }; - - template, class Allocator = allocator > - class basic_string { - public: - explicit basic_string(const Allocator& a = Allocator()); - basic_string(const charT* s, const Allocator& a = Allocator()); - - const charT* c_str() const; - - typedef std::iterator iterator; - typedef std::iterator const_iterator; - - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - const_iterator cbegin() const; - const_iterator cend() const; - }; - - typedef basic_string string; - - template > - class basic_istream /*: virtual public basic_ios - not needed for this test */ { - public: - basic_istream& operator>>(int& n); - }; - - template > - class basic_ostream /*: virtual public basic_ios - not needed for this test */ { - public: - typedef charT char_type; - basic_ostream& write(const char_type* s, streamsize n); - - basic_ostream& operator<<(int n); - }; - - template basic_ostream& operator<<(basic_ostream&, const charT*); - template basic_ostream& operator<<(basic_ostream& os, const basic_string& str); - - template> - class basic_iostream : public basic_istream, public basic_ostream { - public: - }; - - template, class Allocator = allocator> - class basic_stringstream : public basic_iostream { - public: - explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/); - - basic_string str() const; - }; - - using stringstream = basic_stringstream; -} - -char *source(); -void sink(const char *s) {}; -void sink(const std::string &s) {}; -void sink(const std::stringstream &s) {}; - -void test_string() -{ - char *a = source(); - std::string b("123"); - std::string c(source()); - - sink(a); // tainted - sink(b); - sink(c); // tainted - sink(b.c_str()); - sink(c.c_str()); // tainted -} - -void test_stringstream() -{ - std::stringstream ss1, ss2, ss3, ss4, ss5; - std::string t(source()); - - ss1 << "1234"; - ss2 << source(); - ss3 << "123" << source(); - ss4 << source() << "456"; - ss5 << t; - - sink(ss1); - sink(ss2); // tainted [NOT DETECTED] - sink(ss3); // tainted [NOT DETECTED] - sink(ss4); // tainted [NOT DETECTED] - sink(ss5); // tainted [NOT DETECTED] - sink(ss1.str()); - sink(ss2.str()); // tainted [NOT DETECTED] - sink(ss3.str()); // tainted [NOT DETECTED] - sink(ss4.str()); // tainted [NOT DETECTED] - sink(ss5.str()); // tainted [NOT DETECTED] -} - -void test_stringstream_int(int source) -{ - std::stringstream ss1, ss2; - - ss1 << 1234; - ss2 << source; - - sink(ss1); - sink(ss2); // tainted [NOT DETECTED] - sink(ss1.str()); - sink(ss2.str()); // tainted [NOT DETECTED] -} - -using namespace std; - -char *user_input() { - return source(); -} - -void sink(const char *filename, const char *mode); - -void test_strings2() -{ - string path1 = user_input(); - sink(path1.c_str(), "r"); // tainted - - string path2; - path2 = user_input(); - sink(path2.c_str(), "r"); // tainted - - string path3(user_input()); - sink(path3.c_str(), "r"); // tainted -} - -void test_string3() -{ - const char *cs = source(); - - // convert char * -> std::string - std::string ss(cs); - - sink(cs); // tainted - sink(ss); // tainted -} - -void test_string4() -{ - const char *cs = source(); - - // convert char * -> std::string - std::string ss(cs); - - // convert back std::string -> char * - cs = ss.c_str(); - - sink(cs); // tainted - sink(ss); // tainted -} - -void test_string_constructors_assignments() -{ - { - std::string s1("hello"); - std::string s2 = "hello"; - std::string s3; - s3 = "hello"; - - sink(s1); - sink(s2); - sink(s3); - } - - { - std::string s1(source()); - std::string s2 = source(); - std::string s3; - s3 = source(); - - sink(s1); // tainted - sink(s2); // tainted - sink(s3); // tainted - } - - { - std::string s1; - std::string s2 = s1; - std::string s3; - s3 = s1; - - sink(s1); - sink(s2); - sink(s3); - } - - { - std::string s1 = std::string(source()); - std::string s2; - s2 = std::string(source()); - - sink(s1); // tainted - sink(s2); // tainted - } -} - -void sink(char) {} - -void test_range_based_for_loop_string() { - std::string s(source()); - for(char c : s) { - sink(c); // tainted [NOT DETECTED by IR] - } - - for(std::string::iterator it = s.begin(); it != s.end(); ++it) { - sink(*it); // tainted [NOT DETECTED] - } - - for(char& c : s) { - sink(c); // tainted [NOT DETECTED by IR] - } - - const std::string const_s(source()); - for(const char& c : const_s) { - sink(c); // tainted [NOT DETECTED by IR] - } -} - - - - - - - - -namespace std { - template - class vector { - private: - void *data_; - public: - vector(int size); - - T& operator[](int idx); - const T& operator[](int idx) const; - - typedef std::iterator iterator; - typedef std::iterator const_iterator; - - iterator begin() noexcept; - iterator end() noexcept; - - const_iterator begin() const noexcept; - const_iterator end() const noexcept; - }; -} - -void sink(int); - -void test_range_based_for_loop_vector(int source1) { - // Tainting the vector by allocating a tainted length. This doesn't represent - // how a vector would typically get tainted, but it allows this test to avoid - // being concerned with std::vector modeling. - std::vector v(source1); - - for(int x : v) { - sink(x); // tainted [NOT DETECTED by IR] - } - - for(std::vector::iterator it = v.begin(); it != v.end(); ++it) { - sink(*it); // tainted [NOT DETECTED] - } - - for(int& x : v) { - sink(x); // tainted [NOT DETECTED by IR] - } - - const std::vector const_v(source1); - for(const int& x : const_v) { - sink(x); // tainted [NOT DETECTED by IR] - } -} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h new file mode 100644 index 00000000000..c6a27a870ac --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -0,0 +1,169 @@ + +typedef unsigned long size_t; + +// --- string --- + +namespace std +{ + template struct char_traits; + + typedef size_t streamsize; + + struct ptrdiff_t; + + template + struct iterator { + iterator &operator++(); + iterator operator++(int); + bool operator==(iterator other) const; + bool operator!=(iterator other) const; + reference_type operator*() const; + }; + + struct input_iterator_tag {}; + struct forward_iterator_tag : public input_iterator_tag {}; + struct bidirectional_iterator_tag : public forward_iterator_tag {}; + struct random_access_iterator_tag : public bidirectional_iterator_tag {}; + + template class allocator { + public: + allocator() throw(); + typedef size_t size_type; + }; + + template, class Allocator = allocator > + 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 iterator; + typedef std::iterator const_iterator; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; + + template basic_string& operator+=(const T& t); + basic_string& operator+=(const charT* s); + 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::propagate_on_container_swap::value || allocator_traits::is_always_equal::value)*/; + }; + + template basic_string operator+(const basic_string& lhs, const basic_string& rhs); + template basic_string operator+(const basic_string& lhs, const charT* rhs); + + typedef basic_string string; + + template > + class basic_istream /*: virtual public basic_ios - not needed for this test */ { + public: + basic_istream& operator>>(int& n); + }; + + template > + class basic_ostream /*: virtual public basic_ios - not needed for this test */ { + public: + typedef charT char_type; + basic_ostream& write(const char_type* s, streamsize n); + + basic_ostream& operator<<(int n); + }; + + template basic_ostream& operator<<(basic_ostream&, const charT*); + template basic_ostream& operator<<(basic_ostream& os, const basic_string& str); + + template> + class basic_iostream : public basic_istream, public basic_ostream { + public: + }; + + template, class Allocator = allocator> + class basic_stringstream : public basic_iostream { + public: + explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/); + + basic_string str() const; + }; + + using stringstream = basic_stringstream; +} + +// --- vector --- + +namespace std { + template> + class vector { + public: + using value_type = T; + using reference = value_type&; + using const_reference = const value_type&; + using size_type = unsigned int; + using iterator = std::iterator; + using const_iterator = std::iterator; + + vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { } + explicit vector(const Allocator&) noexcept; + explicit vector(size_type n, const Allocator& = Allocator()); + vector(size_type n, const T& value, const Allocator& = Allocator()); + ~vector(); + + vector& operator=(const vector& x); + vector& operator=(vector&& x) noexcept/*(allocator_traits::propagate_on_container_move_assignment::value || allocator_traits::is_always_equal::value)*/; + + iterator begin() noexcept; + const_iterator begin() const noexcept; + iterator end() noexcept; + const_iterator end() const noexcept; + + size_type size() const noexcept; + + reference operator[](size_type n); + const_reference operator[](size_type n) const; + const_reference at(size_type n) const; + reference at(size_type n); + reference front(); + const_reference front() const; + reference back(); + const_reference back() const; + + T* data() noexcept; + const T* data() const noexcept; + + void push_back(const T& x); + void push_back(T&& x); + + iterator insert(const_iterator position, const T& x); + iterator insert(const_iterator position, T&& x); + iterator insert(const_iterator position, size_type n, const T& x); + + void swap(vector&) noexcept/*(allocator_traits::propagate_on_container_swap::value || allocator_traits::is_always_equal::value)*/; + + void clear() noexcept; + }; +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp new file mode 100644 index 00000000000..8fefb7daf52 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/string.cpp @@ -0,0 +1,323 @@ + +#include "stl.h" + +using namespace std; + +char *source(); + +namespace ns_char +{ + char source(); +} + +char *user_input() { + return source(); +} + +void sink(const char *s) {}; +void sink(const std::string &s) {}; +void sink(const char *filename, const char *mode); +void sink(char) {} + +void test_string() +{ + char *a = source(); + std::string b("123"); + std::string c(source()); + + sink(a); // tainted + sink(b); + sink(c); // tainted + sink(b.c_str()); + sink(c.c_str()); // tainted +} + +void test_strings2() +{ + string path1 = user_input(); + sink(path1.c_str(), "r"); // tainted + + string path2; + path2 = user_input(); + sink(path2.c_str(), "r"); // tainted + + string path3(user_input()); + sink(path3.c_str(), "r"); // tainted +} + +void test_string3() +{ + const char *cs = source(); + + // convert char * -> std::string + std::string ss(cs); + + sink(cs); // tainted + sink(ss); // tainted +} + +void test_string4() +{ + const char *cs = source(); + + // convert char * -> std::string + std::string ss(cs); + + // convert back std::string -> char * + cs = ss.c_str(); + + sink(cs); // tainted + sink(ss); // tainted +} + +void test_string_constructors_assignments() +{ + { + std::string s1("hello"); + std::string s2 = "hello"; + std::string s3; + s3 = "hello"; + + sink(s1); + sink(s2); + sink(s3); + } + + { + std::string s1(source()); + std::string s2 = source(); + std::string s3; + s3 = source(); + + sink(s1); // tainted + sink(s2); // tainted + sink(s3); // tainted + } + + { + std::string s1; + std::string s2 = s1; + std::string s3; + s3 = s1; + + sink(s1); + sink(s2); + sink(s3); + } + + { + std::string s1 = std::string(source()); + std::string s2; + s2 = std::string(source()); + + sink(s1); // tainted + sink(s2); // tainted + } +} + +void test_range_based_for_loop_string() { + std::string s(source()); + for(char c : s) { + sink(c); // tainted [NOT DETECTED by IR] + } + + for(std::string::iterator it = s.begin(); it != s.end(); ++it) { + sink(*it); // tainted [NOT DETECTED] + } + + for(char& c : s) { + sink(c); // tainted [NOT DETECTED by IR] + } + + const std::string const_s(source()); + for(const char& c : const_s) { + sink(c); // tainted [NOT DETECTED by IR] + } +} + +void test_string_append() { + { + std::string s1("hello"); + std::string s2(source()); + + sink(s1 + s1); + sink(s1 + s2); // tainted + sink(s2 + s1); // tainted + sink(s2 + s2); // tainted + + sink(s1 + " world"); + sink(s1 + source()); // tainted + } + + { + std::string s3("abc"); + std::string s4(source()); + std::string s5, s6, s7, s8, s9; + + s5 = s3 + s4; + sink(s5); // tainted + + s6 = s3; + s6 += s4; + sink(s6); // tainted + + s7 = s3; + s7 += source(); + s7 += " "; + sink(s7); // tainted + + s8 = s3; + s8.append(s4); + sink(s8); // tainted + + s9 = s3; + s9.append(source()); + s9.append(" "); + sink(s9); // tainted + } + + { + std::string s10("abc"); + char c = ns_char::source(); + + s10.append(1, c); + 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 +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp new file mode 100644 index 00000000000..0656da01277 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stringstream.cpp @@ -0,0 +1,45 @@ + +#include "stl.h" + +using namespace std; + +char *source(); + +void sink(const std::string &s) {}; +void sink(const std::stringstream &s) {}; + +void test_stringstream() +{ + std::stringstream ss1, ss2, ss3, ss4, ss5; + std::string t(source()); + + ss1 << "1234"; + ss2 << source(); + ss3 << "123" << source(); + ss4 << source() << "456"; + ss5 << t; + + sink(ss1); + sink(ss2); // tainted [NOT DETECTED] + sink(ss3); // tainted [NOT DETECTED] + sink(ss4); // tainted [NOT DETECTED] + sink(ss5); // tainted [NOT DETECTED] + sink(ss1.str()); + sink(ss2.str()); // tainted [NOT DETECTED] + sink(ss3.str()); // tainted [NOT DETECTED] + sink(ss4.str()); // tainted [NOT DETECTED] + sink(ss5.str()); // tainted [NOT DETECTED] +} + +void test_stringstream_int(int source) +{ + std::stringstream ss1, ss2; + + ss1 << 1234; + ss2 << source; + + sink(ss1); + sink(ss2); // tainted [NOT DETECTED] + sink(ss1.str()); + sink(ss2.str()); // tainted [NOT DETECTED] +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index cd213ac2055..c14cfb01531 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -32,27 +32,65 @@ | movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source | | movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source | | movableclass.cpp:65:11:65:11 | call to operator= | movableclass.cpp:65:13:65:18 | call to source | -| stl.cpp:101:7:101:7 | a | stl.cpp:97:12:97:17 | call to source | -| stl.cpp:103:7:103:7 | c | stl.cpp:99:16:99:21 | call to source | -| stl.cpp:105:9:105:13 | call to c_str | stl.cpp:99:16:99:21 | call to source | -| stl.cpp:155:13:155:17 | call to c_str | stl.cpp:147:10:147:15 | call to source | -| stl.cpp:159:13:159:17 | call to c_str | stl.cpp:147:10:147:15 | call to source | -| stl.cpp:162:13:162:17 | call to c_str | stl.cpp:147:10:147:15 | call to source | -| stl.cpp:172:7:172:8 | cs | stl.cpp:167:19:167:24 | call to source | -| stl.cpp:173:7:173:8 | ss | stl.cpp:167:19:167:24 | call to source | -| stl.cpp:186:7:186:8 | cs | stl.cpp:178:19:178:24 | call to source | -| stl.cpp:187:7:187:8 | ss | stl.cpp:178:19:178:24 | call to source | -| stl.cpp:209:8:209:9 | s1 | stl.cpp:204:18:204:23 | call to source | -| stl.cpp:210:8:210:9 | s2 | stl.cpp:205:20:205:25 | call to source | -| stl.cpp:211:8:211:9 | s3 | stl.cpp:207:8:207:13 | call to source | -| stl.cpp:230:8:230:9 | s1 | stl.cpp:226:32:226:37 | call to source | -| stl.cpp:231:8:231:9 | s2 | stl.cpp:228:20:228:25 | call to source | -| stl.cpp:240:8:240:8 | c | stl.cpp:238:16:238:21 | call to source | -| stl.cpp:248:8:248:8 | c | stl.cpp:238:16:238:21 | call to source | -| stl.cpp:253:8:253:8 | c | stl.cpp:251:28:251:33 | call to source | -| stl.cpp:295:8:295:8 | x | stl.cpp:288:43:288:49 | source1 | -| stl.cpp:303:8:303:8 | x | stl.cpp:288:43:288:49 | source1 | -| stl.cpp:308:8:308:8 | x | stl.cpp:288:43:288:49 | source1 | +| string.cpp:28:7:28:7 | a | string.cpp:24:12:24:17 | call to source | +| string.cpp:30:7:30:7 | c | string.cpp:26:16:26:21 | call to source | +| string.cpp:32:9:32:13 | call to c_str | string.cpp:26:16:26:21 | call to source | +| string.cpp:38:13:38:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:42:13:42:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:45:13:45:17 | call to c_str | string.cpp:14:10:14:15 | call to source | +| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:24 | call to source | +| string.cpp:56:7:56:8 | ss | string.cpp:50:19:50:24 | call to source | +| string.cpp:69:7:69:8 | cs | string.cpp:61:19:61:24 | call to source | +| string.cpp:70:7:70:8 | ss | string.cpp:61:19:61:24 | call to source | +| string.cpp:92:8:92:9 | s1 | string.cpp:87:18:87:23 | call to source | +| string.cpp:93:8:93:9 | s2 | string.cpp:88:20:88:25 | call to source | +| string.cpp:94:8:94:9 | s3 | string.cpp:90:8:90:13 | call to source | +| string.cpp:113:8:113:9 | s1 | string.cpp:109:32:109:37 | call to source | +| string.cpp:114:8:114:9 | s2 | string.cpp:111:20:111:25 | call to source | +| string.cpp:121:8:121:8 | c | string.cpp:119:16:119:21 | call to source | +| string.cpp:129:8:129:8 | c | string.cpp:119:16:119:21 | call to source | +| string.cpp:134:8:134:8 | c | string.cpp:132:28:132:33 | call to source | +| string.cpp:144:11:144:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | +| string.cpp:145:11:145:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | +| string.cpp:146:11:146:11 | call to operator+ | string.cpp:141:18:141:23 | call to source | +| string.cpp:149:11:149:11 | call to operator+ | string.cpp:149:13:149:18 | call to source | +| string.cpp:158:8:158:9 | s5 | string.cpp:154:18:154:23 | call to source | +| string.cpp:162:8:162:9 | s6 | string.cpp:154:18:154:23 | call to source | +| string.cpp:167:8:167:9 | s7 | string.cpp:165:9:165:14 | call to source | +| 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 | @@ -159,3 +197,21 @@ | taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source | | taint.cpp:471:7:471:7 | y | taint.cpp:462:6:462:11 | call to source | | taint.cpp:485:7:485:10 | line | taint.cpp:480:26:480:32 | source1 | +| vector.cpp:20:8:20:8 | x | vector.cpp:16:43:16:49 | source1 | +| vector.cpp:28:8:28:8 | x | vector.cpp:16:43:16:49 | source1 | +| vector.cpp:33:8:33:8 | x | vector.cpp:16:43:16:49 | source1 | +| vector.cpp:70:7:70:8 | v5 | vector.cpp:69:15:69:20 | call to source | +| vector.cpp:71:10:71:14 | call to front | vector.cpp:69:15:69:20 | call to source | +| vector.cpp:72:10:72:13 | call to back | vector.cpp:69:15:69:20 | call to source | +| vector.cpp:109:7:109:8 | v1 | vector.cpp:106:15:106:20 | call to source | +| vector.cpp:112:7:112:8 | v4 | vector.cpp:107:15:107:20 | call to source | +| vector.cpp:117:7:117:8 | v1 | vector.cpp:106:15:106:20 | call to source | +| vector.cpp:118:7:118:8 | v2 | vector.cpp:106:15:106:20 | call to source | +| vector.cpp:119:7:119:8 | v3 | vector.cpp:107:15:107:20 | call to source | +| vector.cpp:120:7:120:8 | v4 | vector.cpp:107:15:107:20 | call to source | +| vector.cpp:130:7:130:8 | v1 | vector.cpp:126:15:126:20 | call to source | +| vector.cpp:131:7:131:8 | v2 | vector.cpp:127:15:127:20 | call to source | +| vector.cpp:132:7:132:8 | v3 | vector.cpp:128:15:128:20 | call to source | +| vector.cpp:139:7:139:8 | v1 | vector.cpp:126:15:126:20 | call to source | +| vector.cpp:140:7:140:8 | v2 | vector.cpp:127:15:127:20 | call to source | +| vector.cpp:141:7:141:8 | v3 | vector.cpp:128:15:128:20 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index be3b27ea69d..a3e750cdab6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -30,26 +30,64 @@ | movableclass.cpp:55:8:55:9 | movableclass.cpp:52:23:52:28 | AST only | | movableclass.cpp:64:8:64:9 | movableclass.cpp:23:55:23:60 | AST only | | movableclass.cpp:65:11:65:11 | movableclass.cpp:65:13:65:18 | AST only | -| stl.cpp:103:7:103:7 | stl.cpp:99:16:99:21 | AST only | -| stl.cpp:105:9:105:13 | stl.cpp:99:16:99:21 | AST only | -| stl.cpp:155:13:155:17 | stl.cpp:147:10:147:15 | AST only | -| stl.cpp:159:13:159:17 | stl.cpp:147:10:147:15 | AST only | -| stl.cpp:162:13:162:17 | stl.cpp:147:10:147:15 | AST only | -| stl.cpp:172:7:172:8 | stl.cpp:167:19:167:26 | IR only | -| stl.cpp:173:7:173:8 | stl.cpp:167:19:167:24 | AST only | -| stl.cpp:186:7:186:8 | stl.cpp:178:19:178:24 | AST only | -| stl.cpp:187:7:187:8 | stl.cpp:178:19:178:24 | AST only | -| stl.cpp:209:8:209:9 | stl.cpp:204:18:204:23 | AST only | -| stl.cpp:210:8:210:9 | stl.cpp:205:20:205:25 | AST only | -| stl.cpp:211:8:211:9 | stl.cpp:207:8:207:13 | AST only | -| stl.cpp:230:8:230:9 | stl.cpp:226:32:226:37 | AST only | -| stl.cpp:231:8:231:9 | stl.cpp:228:20:228:25 | AST only | -| stl.cpp:240:8:240:8 | stl.cpp:238:16:238:21 | AST only | -| stl.cpp:248:8:248:8 | stl.cpp:238:16:238:21 | AST only | -| stl.cpp:253:8:253:8 | stl.cpp:251:28:251:33 | AST only | -| stl.cpp:295:8:295:8 | stl.cpp:288:43:288:49 | AST only | -| stl.cpp:303:8:303:8 | stl.cpp:288:43:288:49 | AST only | -| stl.cpp:308:8:308:8 | stl.cpp:288:43:288:49 | AST only | +| string.cpp:30:7:30:7 | string.cpp:26:16:26:21 | AST only | +| string.cpp:32:9:32:13 | string.cpp:26:16:26:21 | AST only | +| string.cpp:38:13:38:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:42:13:42:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:45:13:45:17 | string.cpp:14:10:14:15 | AST only | +| string.cpp:55:7:55:8 | string.cpp:50:19:50:26 | IR only | +| string.cpp:56:7:56:8 | string.cpp:50:19:50:24 | AST only | +| string.cpp:69:7:69:8 | string.cpp:61:19:61:24 | AST only | +| string.cpp:70:7:70:8 | string.cpp:61:19:61:24 | AST only | +| string.cpp:92:8:92:9 | string.cpp:87:18:87:23 | AST only | +| string.cpp:93:8:93:9 | string.cpp:88:20:88:25 | AST only | +| string.cpp:94:8:94:9 | string.cpp:90:8:90:13 | AST only | +| string.cpp:113:8:113:9 | string.cpp:109:32:109:37 | AST only | +| string.cpp:114:8:114:9 | string.cpp:111:20:111:25 | AST only | +| string.cpp:121:8:121:8 | string.cpp:119:16:119:21 | AST only | +| string.cpp:129:8:129:8 | string.cpp:119:16:119:21 | AST only | +| string.cpp:134:8:134:8 | string.cpp:132:28:132:33 | AST only | +| string.cpp:144:11:144:11 | string.cpp:141:18:141:23 | AST only | +| string.cpp:145:11:145:11 | string.cpp:141:18:141:23 | AST only | +| string.cpp:146:11:146:11 | string.cpp:141:18:141:23 | AST only | +| string.cpp:149:11:149:11 | string.cpp:149:13:149:18 | AST only | +| string.cpp:158:8:158:9 | string.cpp:154:18:154:23 | AST only | +| string.cpp:162:8:162:9 | string.cpp:154:18:154:23 | AST only | +| string.cpp:167:8:167:9 | string.cpp:165:9:165:14 | AST only | +| 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 | @@ -94,3 +132,21 @@ | taint.cpp:446:7:446:7 | taint.cpp:445:14:445:28 | AST only | | taint.cpp:447:9:447:17 | taint.cpp:445:14:445:28 | AST only | | taint.cpp:471:7:471:7 | taint.cpp:462:6:462:11 | AST only | +| vector.cpp:20:8:20:8 | vector.cpp:16:43:16:49 | AST only | +| vector.cpp:28:8:28:8 | vector.cpp:16:43:16:49 | AST only | +| vector.cpp:33:8:33:8 | vector.cpp:16:43:16:49 | AST only | +| vector.cpp:70:7:70:8 | vector.cpp:69:15:69:20 | AST only | +| vector.cpp:71:10:71:14 | vector.cpp:69:15:69:20 | AST only | +| vector.cpp:72:10:72:13 | vector.cpp:69:15:69:20 | AST only | +| vector.cpp:109:7:109:8 | vector.cpp:106:15:106:20 | AST only | +| vector.cpp:112:7:112:8 | vector.cpp:107:15:107:20 | AST only | +| vector.cpp:117:7:117:8 | vector.cpp:106:15:106:20 | AST only | +| vector.cpp:118:7:118:8 | vector.cpp:106:15:106:20 | AST only | +| vector.cpp:119:7:119:8 | vector.cpp:107:15:107:20 | AST only | +| vector.cpp:120:7:120:8 | vector.cpp:107:15:107:20 | AST only | +| vector.cpp:130:7:130:8 | vector.cpp:126:15:126:20 | AST only | +| vector.cpp:131:7:131:8 | vector.cpp:127:15:127:20 | AST only | +| vector.cpp:132:7:132:8 | vector.cpp:128:15:128:20 | AST only | +| vector.cpp:139:7:139:8 | vector.cpp:126:15:126:20 | AST only | +| vector.cpp:140:7:140:8 | vector.cpp:127:15:127:20 | AST only | +| vector.cpp:141:7:141:8 | vector.cpp:128:15:128:20 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index 62debb5d11f..ac79007f6a7 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,10 +1,10 @@ | format.cpp:157:7:157:22 | (int)... | format.cpp:147:12:147:25 | call to source | | format.cpp:157:7:157:22 | access to array | format.cpp:147:12:147:25 | call to source | | format.cpp:158:7:158:27 | ... + ... | format.cpp:148:16:148:30 | call to source | -| stl.cpp:101:7:101:7 | (const char *)... | stl.cpp:97:12:97:17 | call to source | -| stl.cpp:101:7:101:7 | a | stl.cpp:97:12:97:17 | call to source | -| stl.cpp:172:7:172:8 | cs | stl.cpp:167:19:167:24 | call to source | -| stl.cpp:172:7:172:8 | cs | stl.cpp:167:19:167:26 | (const char *)... | +| string.cpp:28:7:28:7 | (const char *)... | string.cpp:24:12:24:17 | call to source | +| string.cpp:28:7:28:7 | a | string.cpp:24:12:24:17 | call to source | +| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:24 | call to source | +| string.cpp:55:7:55:8 | cs | string.cpp:50:19:50:26 | (const char *)... | | structlikeclass.cpp:38:8:38:9 | s4 | structlikeclass.cpp:33:8:33:13 | call to source | | structlikeclass.cpp:61:8:61:9 | s2 | structlikeclass.cpp:58:24:58:29 | call to source | | structlikeclass.cpp:62:8:62:20 | ... = ... | structlikeclass.cpp:62:13:62:18 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp new file mode 100644 index 00000000000..4bad4ed3cc1 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -0,0 +1,143 @@ + +#include "stl.h" + +using namespace std; + +int source(); + +namespace ns_char +{ + char source(); +} + +void sink(int); +void sink(std::vector &); + +void test_range_based_for_loop_vector(int source1) { + std::vector v(100, source1); + + for(int x : v) { + sink(x); // tainted [NOT DETECTED by IR] + } + + for(std::vector::iterator it = v.begin(); it != v.end(); ++it) { + sink(*it); // tainted [NOT DETECTED] + } + + for(int& x : v) { + sink(x); // tainted [NOT DETECTED by IR] + } + + const std::vector const_v(100, source1); + for(const int& x : const_v) { + sink(x); // tainted [NOT DETECTED by IR] + } +} + +void test_element_taint(int x) { + std::vector v1(10), v2(10), v3(10), v4(10), v5(10), v6(10), v7(10), v8(10), v9(10); + + v1[0] = 0; + v1[1] = 0; + v1[x] = 0; + v1.push_back(1); + sink(v1); + sink(v1[0]); + sink(v1[1]); + sink(v1[x]); + sink(v1.front()); + sink(v1.back()); + + v2[0] = source(); + sink(v2); // tainted [NOT DETECTED] + sink(v2[0]); // tainted [NOT DETECTED] + sink(v2[1]); + sink(v2[x]); // potentially tainted + + v3 = v2; + sink(v3); // tainted [NOT DETECTED] + sink(v3[0]); // tainted [NOT DETECTED] + sink(v3[1]); + sink(v3[x]); // potentially tainted + + v4[x] = source(); + sink(v4); // tainted [NOT DETECTED] + sink(v4[0]); // potentially tainted + sink(v4[1]); // potentially tainted + sink(v4[x]); // tainted [NOT DETECTED] + + v5.push_back(source()); + sink(v5); // tainted + sink(v5.front()); // [FALSE POSITIVE] + sink(v5.back()); // tainted + + v6.data()[2] = source(); + sink(v6); // tainted [NOT DETECTED] + sink(v6.data()[2]); // tainted [NOT DETECTED] + + { + const std::vector &v7c = v7; // (workaround because our iterators don't convert to const_iterator) + std::vector::const_iterator it = v7c.begin(); + v7.insert(it, source()); + } + sink(v7); // tainted [NOT DETECTED] + sink(v7.front()); // tainted [NOT DETECTED] + sink(v7.back()); + + { + const std::vector &v8c = v8; + std::vector::const_iterator it = v8c.begin(); + v8.insert(it, 10, ns_char::source()); + } + sink(v8); // tainted [NOT DETECTED] + sink(v8.front()); // tainted [NOT DETECTED] + sink(v8.back()); + + v9.at(x) = source(); + sink(v9); // tainted [NOT DETECTED] + sink(v9.at(0)); // potentially tainted + sink(v9.at(1)); // potentially tainted + sink(v9.at(x)); // tainted [NOT DETECTED] +} + +void test_vector_swap() { + std::vector v1(10), v2(10), v3(10), v4(10); + + v1.push_back(source()); + v4.push_back(source()); + + sink(v1); // tainted + sink(v2); + sink(v3); + sink(v4); // tainted + + v1.swap(v2); + v3.swap(v4); + + sink(v1); // [FALSE POSITIVE] + sink(v2); // tainted + sink(v3); // tainted + sink(v4); // [FALSE POSITIVE] +} + +void test_vector_clear() { + std::vector v1(10), v2(10), v3(10), v4(10); + + v1.push_back(source()); + v2.push_back(source()); + v3.push_back(source()); + + sink(v1); // tainted + sink(v2); // tainted + sink(v3); // tainted + sink(v4); + + v1.clear(); + v2 = v2; + v3 = v4; + + sink(v1); // [FALSE POSITIVE] + sink(v2); // tainted + sink(v3); // [FALSE POSITIVE] + sink(v4); +} diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index b8788c5c6aa..34886b1f343 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -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; } -}; \ No newline at end of file +}; diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected index 4ad86a3d2ab..d3b696ad316 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected @@ -1,524 +1,575 @@ -| inline_assembly.c:10:3:10:3 | y | 0.0 | -| inline_assembly.c:12:29:12:29 | x | 0.0 | -| inline_assembly.c:12:32:12:32 | y | 1.0 | -| inline_assembly.c:16:25:16:25 | x | 0.0 | -| inline_assembly.c:16:35:16:35 | y | 1.0 | -| inline_assembly.c:21:29:21:29 | x | 0.0 | -| inline_assembly.c:21:32:21:32 | y | 0.0 | -| minmax.c:18:37:18:37 | x | 1.0 | -| minmax.c:18:40:18:40 | y | 2.0 | -| minmax.c:18:43:18:43 | z | 3.0 | -| minmax.c:20:2:20:2 | z | -2.147483648E9 | -| minmax.c:22:8:22:8 | x | 1.0 | -| minmax.c:22:14:22:14 | y | 2.0 | -| minmax.c:22:18:22:18 | t | -2.147483648E9 | -| minmax.c:22:22:22:22 | x | 1.0 | -| minmax.c:23:3:23:3 | t | 0.0 | -| minmax.c:26:37:26:37 | x | 1.0 | -| minmax.c:26:40:26:40 | y | 2.0 | -| minmax.c:26:43:26:43 | z | 0.0 | -| test.c:8:5:8:9 | count | -2.147483648E9 | -| test.c:8:13:8:17 | count | -2.147483648E9 | -| test.c:10:10:10:14 | count | -2.147483648E9 | -| test.c:16:5:16:9 | count | -2.147483648E9 | -| test.c:16:14:16:18 | count | 0.0 | -| test.c:18:10:18:14 | count | 0.0 | -| test.c:24:5:24:9 | count | 0.0 | -| test.c:25:5:25:9 | count | -2.147483648E9 | -| test.c:25:13:25:17 | count | 1.0 | -| test.c:27:10:27:14 | count | 0.0 | -| test.c:33:8:33:8 | i | -2.147483648E9 | -| test.c:33:15:33:15 | i | 0.0 | -| test.c:33:22:33:22 | i | -2.147483648E9 | -| test.c:33:26:33:26 | i | 0.0 | -| test.c:34:5:34:9 | total | -2.147483648E9 | -| test.c:34:14:34:14 | i | 0.0 | -| test.c:36:10:36:14 | total | -2.147483648E9 | -| test.c:36:18:36:18 | i | 2.0 | -| test.c:42:8:42:8 | i | -2.147483648E9 | -| test.c:42:15:42:15 | i | 0.0 | -| test.c:42:22:42:22 | i | 0.0 | -| test.c:43:5:43:9 | total | -2.147483648E9 | -| test.c:43:14:43:14 | i | 0.0 | -| test.c:45:10:45:14 | total | -2.147483648E9 | -| test.c:45:18:45:18 | i | 2.0 | -| test.c:51:8:51:8 | i | -2.147483648E9 | -| test.c:51:15:51:15 | i | 0.0 | -| test.c:51:24:51:24 | i | -2.147483648E9 | -| test.c:51:28:51:28 | i | 0.0 | -| test.c:52:5:52:9 | total | -2.147483648E9 | -| test.c:52:14:52:14 | i | 0.0 | -| test.c:54:10:54:14 | total | -2.147483648E9 | -| test.c:54:18:54:18 | i | 2.0 | -| test.c:58:7:58:7 | i | -2.147483648E9 | -| test.c:59:9:59:9 | i | -2.147483648E9 | -| test.c:60:14:60:14 | i | -2.147483648E9 | -| test.c:67:15:67:15 | y | -2.147483648E9 | -| test.c:67:20:67:20 | y | -999.0 | -| test.c:68:9:68:9 | x | -2.147483648E9 | -| test.c:68:13:68:13 | y | -999.0 | -| test.c:69:14:69:14 | x | -2.147483648E9 | -| test.c:72:10:72:10 | y | -2.147483648E9 | -| test.c:76:7:76:7 | y | -2.147483648E9 | -| test.c:77:9:77:9 | x | -2.147483648E9 | -| test.c:81:9:81:9 | x | -2.147483648E9 | -| test.c:85:10:85:10 | x | 4.0 | -| test.c:89:7:89:7 | y | -2.147483648E9 | -| test.c:90:9:90:9 | x | -2.147483648E9 | -| test.c:90:13:90:13 | y | 8.0 | -| test.c:93:12:93:12 | x | 8.0 | -| test.c:100:3:100:3 | c | -128.0 | -| test.c:101:7:101:7 | c | -128.0 | -| test.c:104:7:104:7 | c | -128.0 | -| test.c:105:5:105:5 | c | -128.0 | -| test.c:106:9:106:9 | c | -128.0 | -| test.c:109:9:109:9 | c | -128.0 | -| test.c:119:10:119:10 | n | 0.0 | -| test.c:124:11:124:15 | Start | 0.0 | -| test.c:127:6:127:10 | Start | 0.0 | -| test.c:127:15:127:20 | Length | 0.0 | -| test.c:135:22:135:22 | c | -128.0 | -| test.c:137:20:137:20 | x | 0.0 | -| test.c:138:11:138:11 | i | -2.147483648E9 | -| test.c:139:19:139:19 | c | -128.0 | -| test.c:139:23:139:23 | i | -2.147483648E9 | -| test.c:139:27:139:28 | uc | 0.0 | -| test.c:139:32:139:32 | x | 0.0 | -| test.c:139:36:139:36 | y | 0.0 | -| test.c:139:40:139:40 | z | -2.147483648E9 | -| test.c:144:23:144:23 | x | -2.147483648E9 | -| test.c:145:32:145:32 | x | -2.147483648E9 | -| test.c:146:33:146:33 | x | -2.147483648E9 | -| test.c:147:31:147:31 | x | -2.147483648E9 | -| test.c:148:13:148:13 | x | -2.147483648E9 | -| test.c:149:23:149:23 | x | -2.147483648E9 | -| test.c:150:10:150:11 | x0 | -128.0 | -| test.c:150:15:150:16 | x1 | 0.0 | -| test.c:150:20:150:21 | x2 | 0.0 | -| test.c:150:25:150:26 | x3 | -2.147483648E9 | -| test.c:150:30:150:31 | c0 | -128.0 | -| test.c:150:35:150:36 | s0 | 0.0 | -| test.c:154:11:154:11 | x | -9.223372036854776E18 | -| test.c:154:20:154:20 | x | 1.0 | -| test.c:154:30:154:30 | x | 1.0 | -| test.c:154:35:154:35 | x | 1.0 | -| test.c:161:12:161:12 | a | -2.147483648E9 | -| test.c:161:17:161:17 | a | 3.0 | -| test.c:162:14:162:14 | a | 3.0 | -| test.c:163:14:163:14 | a | 3.0 | -| test.c:164:5:164:9 | total | 0.0 | -| test.c:164:14:164:14 | b | 3.0 | -| test.c:164:16:164:16 | c | -11.0 | -| test.c:166:12:166:12 | a | -2.147483648E9 | -| test.c:166:17:166:17 | a | 0.0 | -| test.c:167:14:167:14 | a | 0.0 | -| test.c:168:14:168:14 | a | 0.0 | -| test.c:169:5:169:9 | total | -8.0 | -| test.c:169:14:169:14 | b | 0.0 | -| test.c:169:16:169:16 | c | -11.0 | -| test.c:171:13:171:13 | a | -2.147483648E9 | -| test.c:171:18:171:18 | a | -7.0 | -| test.c:172:14:172:14 | a | -7.0 | -| test.c:173:14:173:14 | a | -7.0 | -| test.c:174:5:174:9 | total | -19.0 | -| test.c:174:14:174:14 | b | -7.0 | -| test.c:174:16:174:16 | c | -11.0 | -| test.c:176:13:176:13 | a | -2.147483648E9 | -| test.c:176:18:176:18 | a | -7.0 | -| test.c:177:14:177:14 | a | -7.0 | -| test.c:178:14:178:14 | a | -7.0 | -| test.c:179:5:179:9 | total | -37.0 | -| test.c:179:14:179:14 | b | -7.0 | -| test.c:179:16:179:16 | c | -1.0 | -| test.c:181:13:181:13 | a | -2.147483648E9 | -| test.c:181:18:181:18 | a | -7.0 | -| test.c:182:14:182:14 | a | -7.0 | -| test.c:183:14:183:14 | a | -7.0 | -| test.c:184:5:184:9 | total | -45.0 | -| test.c:184:14:184:14 | b | -7.0 | -| test.c:184:16:184:16 | c | -0.0 | -| test.c:186:13:186:13 | a | -2.147483648E9 | -| test.c:186:18:186:18 | a | -7.0 | -| test.c:187:14:187:14 | a | -7.0 | -| test.c:188:14:188:14 | a | -7.0 | -| test.c:189:5:189:9 | total | -52.0 | -| test.c:189:14:189:14 | b | -7.0 | -| test.c:189:16:189:16 | c | 2.0 | -| test.c:192:10:192:14 | total | -57.0 | -| test.c:200:12:200:12 | a | -2.147483648E9 | -| test.c:200:17:200:17 | a | 3.0 | -| test.c:200:33:200:33 | b | -2.147483648E9 | -| test.c:200:38:200:38 | b | 5.0 | -| test.c:201:13:201:13 | a | 3.0 | -| test.c:201:15:201:15 | b | 5.0 | -| test.c:202:5:202:9 | total | 0.0 | -| test.c:202:14:202:14 | r | -2.147483648E9 | -| test.c:204:12:204:12 | a | -2.147483648E9 | -| test.c:204:17:204:17 | a | 3.0 | -| test.c:204:33:204:33 | b | -2.147483648E9 | -| test.c:204:38:204:38 | b | 0.0 | -| test.c:205:13:205:13 | a | 3.0 | -| test.c:205:15:205:15 | b | 0.0 | -| test.c:206:5:206:9 | total | -2.147483648E9 | -| test.c:206:14:206:14 | r | -2.147483648E9 | -| test.c:208:12:208:12 | a | -2.147483648E9 | -| test.c:208:17:208:17 | a | 3.0 | -| test.c:208:35:208:35 | b | -2.147483648E9 | -| test.c:208:40:208:40 | b | -13.0 | -| test.c:209:13:209:13 | a | 3.0 | -| test.c:209:15:209:15 | b | -13.0 | -| test.c:210:5:210:9 | total | -2.147483648E9 | -| test.c:210:14:210:14 | r | -2.147483648E9 | -| test.c:212:12:212:12 | a | -2.147483648E9 | -| test.c:212:17:212:17 | a | 3.0 | -| test.c:212:35:212:35 | b | -2.147483648E9 | -| test.c:212:40:212:40 | b | -13.0 | -| test.c:213:13:213:13 | a | 3.0 | -| test.c:213:15:213:15 | b | -13.0 | -| test.c:214:5:214:9 | total | -2.147483648E9 | -| test.c:214:14:214:14 | r | -2.147483648E9 | -| test.c:216:12:216:12 | a | -2.147483648E9 | -| test.c:216:17:216:17 | a | 3.0 | -| test.c:216:35:216:35 | b | -2.147483648E9 | -| test.c:216:40:216:40 | b | -13.0 | -| test.c:217:13:217:13 | a | 3.0 | -| test.c:217:15:217:15 | b | -13.0 | -| test.c:218:5:218:9 | total | -2.147483648E9 | -| test.c:218:14:218:14 | r | -2.147483648E9 | -| test.c:221:10:221:14 | total | -2.147483648E9 | -| test.c:228:12:228:12 | a | -2.147483648E9 | -| test.c:228:17:228:17 | a | 0.0 | -| test.c:228:33:228:33 | b | -2.147483648E9 | -| test.c:228:38:228:38 | b | 5.0 | -| test.c:229:13:229:13 | a | 0.0 | -| test.c:229:15:229:15 | b | 5.0 | -| test.c:230:5:230:9 | total | 0.0 | -| test.c:230:14:230:14 | r | -2.147483648E9 | -| test.c:232:12:232:12 | a | -2.147483648E9 | -| test.c:232:17:232:17 | a | 0.0 | -| test.c:232:33:232:33 | b | -2.147483648E9 | -| test.c:232:38:232:38 | b | 0.0 | -| test.c:233:13:233:13 | a | 0.0 | -| test.c:233:15:233:15 | b | 0.0 | -| test.c:234:5:234:9 | total | -2.147483648E9 | -| test.c:234:14:234:14 | r | -2.147483648E9 | -| test.c:236:12:236:12 | a | -2.147483648E9 | -| test.c:236:17:236:17 | a | 0.0 | -| test.c:236:35:236:35 | b | -2.147483648E9 | -| test.c:236:40:236:40 | b | -13.0 | -| test.c:237:13:237:13 | a | 0.0 | -| test.c:237:15:237:15 | b | -13.0 | -| test.c:238:5:238:9 | total | -2.147483648E9 | -| test.c:238:14:238:14 | r | -2.147483648E9 | -| test.c:240:12:240:12 | a | -2.147483648E9 | -| test.c:240:17:240:17 | a | 0.0 | -| test.c:240:35:240:35 | b | -2.147483648E9 | -| test.c:240:40:240:40 | b | -13.0 | -| test.c:241:13:241:13 | a | 0.0 | -| test.c:241:15:241:15 | b | -13.0 | -| test.c:242:5:242:9 | total | -2.147483648E9 | -| test.c:242:14:242:14 | r | -2.147483648E9 | -| test.c:244:12:244:12 | a | -2.147483648E9 | -| test.c:244:17:244:17 | a | 0.0 | -| test.c:244:35:244:35 | b | -2.147483648E9 | -| test.c:244:40:244:40 | b | -13.0 | -| test.c:245:13:245:13 | a | 0.0 | -| test.c:245:15:245:15 | b | -13.0 | -| test.c:246:5:246:9 | total | -2.147483648E9 | -| test.c:246:14:246:14 | r | -2.147483648E9 | -| test.c:249:10:249:14 | total | -2.147483648E9 | -| test.c:256:14:256:14 | a | -2.147483648E9 | -| test.c:256:19:256:19 | a | -17.0 | -| test.c:256:35:256:35 | b | -2.147483648E9 | -| test.c:256:40:256:40 | b | 5.0 | -| test.c:257:13:257:13 | a | -17.0 | -| test.c:257:15:257:15 | b | 5.0 | -| test.c:258:5:258:9 | total | 0.0 | -| test.c:258:14:258:14 | r | -2.147483648E9 | -| test.c:260:14:260:14 | a | -2.147483648E9 | -| test.c:260:19:260:19 | a | -17.0 | -| test.c:260:35:260:35 | b | -2.147483648E9 | -| test.c:260:40:260:40 | b | 0.0 | -| test.c:261:13:261:13 | a | -17.0 | -| test.c:261:15:261:15 | b | 0.0 | -| test.c:262:5:262:9 | total | -2.147483648E9 | -| test.c:262:14:262:14 | r | -2.147483648E9 | -| test.c:264:14:264:14 | a | -2.147483648E9 | -| test.c:264:19:264:19 | a | -17.0 | -| test.c:264:37:264:37 | b | -2.147483648E9 | -| test.c:264:42:264:42 | b | -13.0 | -| test.c:265:13:265:13 | a | -17.0 | -| test.c:265:15:265:15 | b | -13.0 | -| test.c:266:5:266:9 | total | -2.147483648E9 | -| test.c:266:14:266:14 | r | -2.147483648E9 | -| test.c:268:14:268:14 | a | -2.147483648E9 | -| test.c:268:19:268:19 | a | -17.0 | -| test.c:268:37:268:37 | b | -2.147483648E9 | -| test.c:268:42:268:42 | b | -13.0 | -| test.c:269:13:269:13 | a | -17.0 | -| test.c:269:15:269:15 | b | -13.0 | -| test.c:270:5:270:9 | total | -2.147483648E9 | -| test.c:270:14:270:14 | r | -2.147483648E9 | -| test.c:272:14:272:14 | a | -2.147483648E9 | -| test.c:272:19:272:19 | a | -17.0 | -| test.c:272:37:272:37 | b | -2.147483648E9 | -| test.c:272:42:272:42 | b | -13.0 | -| test.c:273:13:273:13 | a | -17.0 | -| test.c:273:15:273:15 | b | -13.0 | -| test.c:274:5:274:9 | total | -2.147483648E9 | -| test.c:274:14:274:14 | r | -2.147483648E9 | -| test.c:277:10:277:14 | total | -2.147483648E9 | -| test.c:284:14:284:14 | a | -2.147483648E9 | -| test.c:284:19:284:19 | a | -17.0 | -| test.c:284:34:284:34 | b | -2.147483648E9 | -| test.c:284:39:284:39 | b | 5.0 | -| test.c:285:13:285:13 | a | -17.0 | -| test.c:285:15:285:15 | b | 5.0 | -| test.c:286:5:286:9 | total | 0.0 | -| test.c:286:14:286:14 | r | -2.147483648E9 | -| test.c:288:14:288:14 | a | -2.147483648E9 | -| test.c:288:19:288:19 | a | -17.0 | -| test.c:288:34:288:34 | b | -2.147483648E9 | -| test.c:288:39:288:39 | b | 0.0 | -| test.c:289:13:289:13 | a | -17.0 | -| test.c:289:15:289:15 | b | 0.0 | -| test.c:290:5:290:9 | total | -2.147483648E9 | -| test.c:290:14:290:14 | r | -2.147483648E9 | -| test.c:292:14:292:14 | a | -2.147483648E9 | -| test.c:292:19:292:19 | a | -17.0 | -| test.c:292:36:292:36 | b | -2.147483648E9 | -| test.c:292:41:292:41 | b | -13.0 | -| test.c:293:13:293:13 | a | -17.0 | -| test.c:293:15:293:15 | b | -13.0 | -| test.c:294:5:294:9 | total | -2.147483648E9 | -| test.c:294:14:294:14 | r | -2.147483648E9 | -| test.c:296:14:296:14 | a | -2.147483648E9 | -| test.c:296:19:296:19 | a | -17.0 | -| test.c:296:36:296:36 | b | -2.147483648E9 | -| test.c:296:41:296:41 | b | -13.0 | -| test.c:297:13:297:13 | a | -17.0 | -| test.c:297:15:297:15 | b | -13.0 | -| test.c:298:5:298:9 | total | -2.147483648E9 | -| test.c:298:14:298:14 | r | -2.147483648E9 | -| test.c:300:14:300:14 | a | -2.147483648E9 | -| test.c:300:19:300:19 | a | -17.0 | -| test.c:300:36:300:36 | b | -2.147483648E9 | -| test.c:300:41:300:41 | b | -13.0 | -| test.c:301:13:301:13 | a | -17.0 | -| test.c:301:15:301:15 | b | -13.0 | -| test.c:302:5:302:9 | total | -2.147483648E9 | -| test.c:302:14:302:14 | r | -2.147483648E9 | -| test.c:305:10:305:14 | total | -2.147483648E9 | -| test.c:312:14:312:14 | a | -2.147483648E9 | -| test.c:312:19:312:19 | a | -17.0 | -| test.c:312:35:312:35 | b | -2.147483648E9 | -| test.c:312:40:312:40 | b | 5.0 | -| test.c:313:13:313:13 | a | -17.0 | -| test.c:313:15:313:15 | b | 5.0 | -| test.c:314:5:314:9 | total | 0.0 | -| test.c:314:14:314:14 | r | -2.147483648E9 | -| test.c:316:14:316:14 | a | -2.147483648E9 | -| test.c:316:19:316:19 | a | -17.0 | -| test.c:316:35:316:35 | b | -2.147483648E9 | -| test.c:316:40:316:40 | b | 0.0 | -| test.c:317:13:317:13 | a | -17.0 | -| test.c:317:15:317:15 | b | 0.0 | -| test.c:318:5:318:9 | total | -2.147483648E9 | -| test.c:318:14:318:14 | r | -2.147483648E9 | -| test.c:320:14:320:14 | a | -2.147483648E9 | -| test.c:320:19:320:19 | a | -17.0 | -| test.c:320:37:320:37 | b | -2.147483648E9 | -| test.c:320:42:320:42 | b | -13.0 | -| test.c:321:13:321:13 | a | -17.0 | -| test.c:321:15:321:15 | b | -13.0 | -| test.c:322:5:322:9 | total | -2.147483648E9 | -| test.c:322:14:322:14 | r | -2.147483648E9 | -| test.c:324:14:324:14 | a | -2.147483648E9 | -| test.c:324:19:324:19 | a | -17.0 | -| test.c:324:37:324:37 | b | -2.147483648E9 | -| test.c:324:42:324:42 | b | -13.0 | -| test.c:325:13:325:13 | a | -17.0 | -| test.c:325:15:325:15 | b | -13.0 | -| test.c:326:5:326:9 | total | -2.147483648E9 | -| test.c:326:14:326:14 | r | -2.147483648E9 | -| test.c:328:14:328:14 | a | -2.147483648E9 | -| test.c:328:19:328:19 | a | -17.0 | -| test.c:328:37:328:37 | b | -2.147483648E9 | -| test.c:328:42:328:42 | b | -13.0 | -| test.c:329:13:329:13 | a | -17.0 | -| test.c:329:15:329:15 | b | -13.0 | -| test.c:330:5:330:9 | total | -2.147483648E9 | -| test.c:330:14:330:14 | r | -2.147483648E9 | -| test.c:333:10:333:14 | total | -2.147483648E9 | -| test.c:338:7:338:7 | x | -2.147483648E9 | -| test.c:342:10:342:10 | i | 0.0 | -| test.c:343:5:343:5 | i | 0.0 | -| test.c:345:3:345:3 | d | -2.147483648E9 | -| test.c:345:7:345:7 | i | 3.0 | -| test.c:346:7:346:7 | x | 0.0 | -| test.c:347:9:347:9 | d | 3.0 | -| test.c:347:14:347:14 | x | 0.0 | -| test.c:357:3:357:4 | y1 | 0.0 | -| test.c:357:8:357:8 | x | 0.0 | -| test.c:357:18:357:18 | x | 0.0 | -| test.c:358:3:358:4 | y2 | 0.0 | -| test.c:358:8:358:8 | x | 0.0 | -| test.c:358:24:358:24 | x | 0.0 | -| test.c:359:3:359:4 | y3 | 0.0 | -| test.c:360:3:360:4 | y4 | 0.0 | -| test.c:361:3:361:4 | y5 | 0.0 | -| test.c:362:3:362:4 | y6 | 0.0 | -| test.c:363:3:363:4 | y7 | 0.0 | -| test.c:364:3:364:4 | y8 | 0.0 | -| test.c:365:7:365:7 | x | 0.0 | -| test.c:366:5:366:6 | y3 | 0.0 | -| test.c:366:10:366:10 | x | 0.0 | -| test.c:367:5:367:6 | y4 | 0.0 | -| test.c:367:10:367:10 | x | 0.0 | -| test.c:368:5:368:6 | y5 | 0.0 | -| test.c:368:11:368:11 | x | 0.0 | -| test.c:369:5:369:6 | y6 | 0.0 | -| test.c:369:27:369:27 | x | 0.0 | -| test.c:370:5:370:6 | y7 | 0.0 | -| test.c:370:27:370:27 | x | 0.0 | -| test.c:371:5:371:6 | y8 | 0.0 | -| test.c:371:28:371:28 | x | 0.0 | -| test.c:373:10:373:11 | y1 | 0.0 | -| test.c:373:15:373:16 | y2 | 0.0 | -| test.c:373:20:373:21 | y3 | 0.0 | -| test.c:373:25:373:26 | y4 | 0.0 | -| test.c:373:30:373:31 | y5 | 0.0 | -| test.c:373:35:373:36 | y6 | 0.0 | -| test.c:373:40:373:41 | y7 | 0.0 | -| test.c:373:45:373:46 | y8 | 0.0 | -| test.c:379:3:379:4 | y1 | 0.0 | -| test.c:379:8:379:8 | x | 0.0 | -| test.c:379:18:379:18 | x | 101.0 | -| test.c:380:3:380:4 | y2 | 0.0 | -| test.c:380:8:380:8 | x | 0.0 | -| test.c:380:25:380:25 | x | 101.0 | -| test.c:381:3:381:4 | y3 | 0.0 | -| test.c:382:3:382:4 | y4 | 0.0 | -| test.c:383:3:383:4 | y5 | 0.0 | -| test.c:384:7:384:7 | x | 0.0 | -| test.c:385:5:385:6 | y3 | 0.0 | -| test.c:385:11:385:11 | x | 300.0 | -| test.c:386:5:386:6 | y4 | 0.0 | -| test.c:386:11:386:11 | x | 300.0 | -| test.c:387:5:387:6 | y5 | 0.0 | -| test.c:387:27:387:27 | x | 300.0 | -| test.c:389:10:389:11 | y1 | 101.0 | -| test.c:389:15:389:16 | y2 | 101.0 | -| test.c:389:20:389:21 | y3 | 0.0 | -| test.c:389:25:389:26 | y4 | 100.0 | -| test.c:389:30:389:31 | y5 | 0.0 | -| test.c:394:20:394:20 | x | 0.0 | -| test.c:394:30:394:30 | x | 0.0 | -| test.c:397:3:397:4 | y1 | 0.0 | -| test.c:397:11:397:11 | y | 0.0 | -| test.c:397:14:397:14 | y | 1.0 | -| test.c:398:3:398:4 | y2 | 0.0 | -| test.c:398:9:398:9 | y | 1.0 | -| test.c:398:14:398:14 | y | 2.0 | -| test.c:398:22:398:22 | y | 5.0 | -| test.c:399:10:399:11 | y1 | 1.0 | -| test.c:399:15:399:16 | y2 | 5.0 | -| test.c:407:3:407:3 | i | -2.147483648E9 | -| test.c:408:7:408:7 | i | 10.0 | -| test.c:410:3:410:3 | i | -2.147483648E9 | -| test.c:411:3:411:3 | i | 10.0 | -| test.c:412:7:412:7 | i | -2.147483648E9 | -| test.c:414:3:414:3 | i | -2.147483648E9 | -| test.c:415:3:415:3 | i | 40.0 | -| test.c:416:7:416:7 | i | -2.147483648E9 | -| test.c:418:3:418:3 | i | -2.147483648E9 | -| test.c:418:7:418:7 | j | -2.147483648E9 | -| test.c:419:7:419:7 | i | 40.0 | -| test.c:421:3:421:3 | i | -2.147483648E9 | -| test.c:421:8:421:8 | j | 40.0 | -| test.c:422:7:422:7 | i | 50.0 | -| test.c:424:3:424:3 | i | -2.147483648E9 | -| test.c:424:13:424:13 | j | -2.147483648E9 | -| test.c:425:7:425:7 | i | -2.147483648E9 | -| test.c:432:12:432:12 | a | 0.0 | -| test.c:432:17:432:17 | a | 3.0 | -| test.c:432:33:432:33 | b | 0.0 | -| test.c:432:38:432:38 | b | 5.0 | -| test.c:433:13:433:13 | a | 3.0 | -| test.c:433:15:433:15 | b | 5.0 | -| test.c:434:5:434:9 | total | 0.0 | -| test.c:434:14:434:14 | r | -2.147483648E9 | -| test.c:436:12:436:12 | a | 0.0 | -| test.c:436:17:436:17 | a | 3.0 | -| test.c:436:33:436:33 | b | 0.0 | -| test.c:436:38:436:38 | b | 0.0 | -| test.c:437:13:437:13 | a | 3.0 | -| test.c:437:15:437:15 | b | 0.0 | -| test.c:438:5:438:9 | total | -2.147483648E9 | -| test.c:438:14:438:14 | r | -2.147483648E9 | -| test.c:440:12:440:12 | a | 0.0 | -| test.c:440:17:440:17 | a | 3.0 | -| test.c:440:34:440:34 | b | 0.0 | -| test.c:440:39:440:39 | b | 13.0 | -| test.c:441:13:441:13 | a | 3.0 | -| test.c:441:15:441:15 | b | 13.0 | -| test.c:442:5:442:9 | total | -2.147483648E9 | -| test.c:442:14:442:14 | r | -2.147483648E9 | -| test.c:445:10:445:14 | total | -2.147483648E9 | -| test.c:451:12:451:12 | b | 0.0 | -| test.c:451:17:451:17 | b | 5.0 | -| test.c:452:16:452:16 | b | 5.0 | -| test.c:453:5:453:9 | total | 0.0 | -| test.c:453:14:453:14 | r | -2.147483648E9 | -| test.c:455:12:455:12 | b | 0.0 | -| test.c:455:17:455:17 | b | 0.0 | -| test.c:456:16:456:16 | b | 0.0 | -| test.c:457:5:457:9 | total | -2.147483648E9 | -| test.c:457:14:457:14 | r | -2.147483648E9 | -| test.c:459:13:459:13 | b | 0.0 | -| test.c:459:18:459:18 | b | 13.0 | -| test.c:460:16:460:16 | b | 13.0 | -| test.c:461:5:461:9 | total | -2.147483648E9 | -| test.c:461:14:461:14 | r | -2.147483648E9 | -| test.c:464:10:464:14 | total | -2.147483648E9 | -| test.cpp:10:7:10:7 | b | -2.147483648E9 | -| test.cpp:11:5:11:5 | x | -2.147483648E9 | -| test.cpp:13:10:13:10 | x | -2.147483648E9 | -| test.cpp:18:30:18:30 | x | -2.147483648E9 | -| test.cpp:19:10:19:11 | x0 | -128.0 | -| test.cpp:27:7:27:7 | y | -2.147483648E9 | -| test.cpp:28:5:28:5 | x | -2.147483648E9 | -| test.cpp:30:7:30:7 | y | -2.147483648E9 | -| test.cpp:31:5:31:5 | x | -2.147483648E9 | -| test.cpp:33:7:33:7 | y | -2.147483648E9 | -| test.cpp:34:5:34:5 | x | -2.147483648E9 | -| test.cpp:36:7:36:7 | y | -2.147483648E9 | -| test.cpp:37:5:37:5 | x | -2.147483648E9 | -| test.cpp:39:7:39:7 | y | -2.147483648E9 | -| test.cpp:40:5:40:5 | x | -2.147483648E9 | -| test.cpp:42:7:42:7 | y | -2.147483648E9 | -| test.cpp:43:5:43:5 | x | -2.147483648E9 | -| test.cpp:45:7:45:7 | y | -2.147483648E9 | -| test.cpp:46:5:46:5 | x | -2.147483648E9 | -| test.cpp:51:7:51:7 | x | -2.147483648E9 | -| test.cpp:52:21:52:21 | x | 0.0 | -| test.cpp:53:5:53:5 | t | 0.0 | -| test.cpp:53:15:53:16 | xb | 0.0 | -| test.cpp:56:7:56:7 | x | -2.147483648E9 | -| test.cpp:57:21:57:21 | x | 1.0 | -| test.cpp:58:5:58:5 | t | 0.0 | -| test.cpp:58:15:58:16 | xb | 1.0 | -| test.cpp:61:7:61:7 | x | -2.147483648E9 | -| test.cpp:62:21:62:21 | x | -2.147483648E9 | -| test.cpp:63:5:63:5 | t | 0.0 | -| test.cpp:63:15:63:16 | xb | 1.0 | -| test.cpp:66:19:66:19 | x | -2.147483648E9 | -| test.cpp:67:3:67:3 | t | 0.0 | -| test.cpp:67:13:67:14 | xb | 0.0 | -| test.cpp:69:10:69:10 | b | 0.0 | -| test.cpp:69:21:69:21 | t | 0.0 | -| test.cpp:74:30:74:30 | c | 0.0 | -| test.cpp:74:34:74:34 | c | 0.0 | -| test.cpp:75:22:75:30 | c_times_2 | 0.0 | -| test.cpp:77:5:77:13 | c_times_2 | 0.0 | -| test.cpp:79:3:79:11 | c_times_2 | 0.0 | +| inline_assembly.c:10:3:10:3 | y | 0 | +| inline_assembly.c:12:29:12:29 | x | 0 | +| inline_assembly.c:12:32:12:32 | y | 1 | +| inline_assembly.c:16:25:16:25 | x | 0 | +| inline_assembly.c:16:35:16:35 | y | 1 | +| inline_assembly.c:21:29:21:29 | x | 0 | +| inline_assembly.c:21:32:21:32 | y | 0 | +| minmax.c:18:37:18:37 | x | 1 | +| minmax.c:18:40:18:40 | y | 2 | +| minmax.c:18:43:18:43 | z | 3 | +| minmax.c:20:2:20:2 | z | -2147483648 | +| minmax.c:22:8:22:8 | x | 1 | +| minmax.c:22:14:22:14 | y | 2 | +| minmax.c:22:18:22:18 | t | -2147483648 | +| minmax.c:22:22:22:22 | x | 1 | +| minmax.c:23:3:23:3 | t | 0 | +| minmax.c:26:37:26:37 | x | 1 | +| minmax.c:26:40:26:40 | y | 2 | +| minmax.c:26:43:26:43 | z | 0 | +| test.c:8:5:8:9 | count | -2147483648 | +| test.c:8:13:8:17 | count | -2147483648 | +| test.c:10:10:10:14 | count | -2147483648 | +| test.c:16:5:16:9 | count | -2147483648 | +| test.c:16:14:16:18 | count | 0 | +| test.c:18:10:18:14 | count | 0 | +| test.c:24:5:24:9 | count | 0 | +| test.c:25:5:25:9 | count | -2147483648 | +| test.c:25:13:25:17 | count | 1 | +| test.c:27:10:27:14 | count | 0 | +| test.c:33:8:33:8 | i | -2147483648 | +| test.c:33:15:33:15 | i | 0 | +| test.c:33:22:33:22 | i | -2147483648 | +| test.c:33:26:33:26 | i | 0 | +| test.c:34:5:34:9 | total | -2147483648 | +| test.c:34:14:34:14 | i | 0 | +| test.c:36:10:36:14 | total | -2147483648 | +| test.c:36:18:36:18 | i | 2 | +| test.c:42:8:42:8 | i | -2147483648 | +| test.c:42:15:42:15 | i | 0 | +| test.c:42:22:42:22 | i | 0 | +| test.c:43:5:43:9 | total | -2147483648 | +| test.c:43:14:43:14 | i | 0 | +| test.c:45:10:45:14 | total | -2147483648 | +| test.c:45:18:45:18 | i | 2 | +| test.c:51:8:51:8 | i | -2147483648 | +| test.c:51:15:51:15 | i | 0 | +| test.c:51:24:51:24 | i | -2147483648 | +| test.c:51:28:51:28 | i | 0 | +| test.c:52:5:52:9 | total | -2147483648 | +| test.c:52:14:52:14 | i | 0 | +| test.c:54:10:54:14 | total | -2147483648 | +| test.c:54:18:54:18 | i | 2 | +| test.c:58:7:58:7 | i | -2147483648 | +| test.c:59:9:59:9 | i | -2147483648 | +| test.c:60:14:60:14 | i | -2147483648 | +| test.c:67:15:67:15 | y | -2147483648 | +| test.c:67:20:67:20 | y | -999 | +| test.c:68:9:68:9 | x | -2147483648 | +| test.c:68:13:68:13 | y | -999 | +| test.c:69:14:69:14 | x | -2147483648 | +| test.c:72:10:72:10 | y | -2147483648 | +| test.c:76:7:76:7 | y | -2147483648 | +| test.c:77:9:77:9 | x | -2147483648 | +| test.c:81:9:81:9 | x | -2147483648 | +| test.c:85:10:85:10 | x | 4 | +| test.c:89:7:89:7 | y | -2147483648 | +| test.c:90:9:90:9 | x | -2147483648 | +| test.c:90:13:90:13 | y | 8 | +| test.c:93:12:93:12 | x | 8 | +| test.c:100:3:100:3 | c | -128 | +| test.c:101:7:101:7 | c | -128 | +| test.c:104:7:104:7 | c | -128 | +| test.c:105:5:105:5 | c | -128 | +| test.c:106:9:106:9 | c | -128 | +| test.c:109:9:109:9 | c | -128 | +| test.c:119:10:119:10 | n | 0 | +| test.c:124:11:124:15 | Start | 0 | +| test.c:127:6:127:10 | Start | 0 | +| test.c:127:15:127:20 | Length | 0 | +| test.c:135:22:135:22 | c | -128 | +| test.c:137:20:137:20 | x | 0 | +| test.c:138:11:138:11 | i | -2147483648 | +| test.c:139:19:139:19 | c | -128 | +| test.c:139:23:139:23 | i | -2147483648 | +| test.c:139:27:139:28 | uc | 0 | +| test.c:139:32:139:32 | x | 0 | +| test.c:139:36:139:36 | y | 0 | +| test.c:139:40:139:40 | z | -2147483648 | +| test.c:144:23:144:23 | x | -2147483648 | +| test.c:145:32:145:32 | x | -2147483648 | +| test.c:146:33:146:33 | x | -2147483648 | +| test.c:147:31:147:31 | x | -2147483648 | +| test.c:148:13:148:13 | x | -2147483648 | +| test.c:149:23:149:23 | x | -2147483648 | +| test.c:150:10:150:11 | x0 | -128 | +| test.c:150:15:150:16 | x1 | 0 | +| test.c:150:20:150:21 | x2 | 0 | +| 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 | -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 | +| test.c:161:12:161:12 | a | -2147483648 | +| test.c:161:17:161:17 | a | 3 | +| test.c:162:14:162:14 | a | 3 | +| test.c:163:14:163:14 | a | 3 | +| test.c:164:5:164:9 | total | 0 | +| test.c:164:14:164:14 | b | 3 | +| test.c:164:16:164:16 | c | -11 | +| test.c:166:12:166:12 | a | -2147483648 | +| test.c:166:17:166:17 | a | 0 | +| test.c:167:14:167:14 | a | 0 | +| test.c:168:14:168:14 | a | 0 | +| test.c:169:5:169:9 | total | -8 | +| test.c:169:14:169:14 | b | 0 | +| test.c:169:16:169:16 | c | -11 | +| test.c:171:13:171:13 | a | -2147483648 | +| test.c:171:18:171:18 | a | -7 | +| test.c:172:14:172:14 | a | -7 | +| test.c:173:14:173:14 | a | -7 | +| test.c:174:5:174:9 | total | -19 | +| test.c:174:14:174:14 | b | -7 | +| test.c:174:16:174:16 | c | -11 | +| test.c:176:13:176:13 | a | -2147483648 | +| test.c:176:18:176:18 | a | -7 | +| test.c:177:14:177:14 | a | -7 | +| test.c:178:14:178:14 | a | -7 | +| test.c:179:5:179:9 | total | -37 | +| test.c:179:14:179:14 | b | -7 | +| test.c:179:16:179:16 | c | -1 | +| test.c:181:13:181:13 | a | -2147483648 | +| test.c:181:18:181:18 | a | -7 | +| test.c:182:14:182:14 | a | -7 | +| test.c:183:14:183:14 | a | -7 | +| test.c:184:5:184:9 | total | -45 | +| test.c:184:14:184:14 | b | -7 | +| test.c:184:16:184:16 | c | -0 | +| test.c:186:13:186:13 | a | -2147483648 | +| test.c:186:18:186:18 | a | -7 | +| test.c:187:14:187:14 | a | -7 | +| test.c:188:14:188:14 | a | -7 | +| test.c:189:5:189:9 | total | -52 | +| test.c:189:14:189:14 | b | -7 | +| test.c:189:16:189:16 | c | 2 | +| test.c:192:10:192:14 | total | -57 | +| test.c:200:12:200:12 | a | -2147483648 | +| test.c:200:17:200:17 | a | 3 | +| test.c:200:33:200:33 | b | -2147483648 | +| test.c:200:38:200:38 | b | 5 | +| test.c:201:13:201:13 | a | 3 | +| test.c:201:15:201:15 | b | 5 | +| test.c:202:5:202:9 | total | 0 | +| test.c:202:14:202:14 | r | -2147483648 | +| test.c:204:12:204:12 | a | -2147483648 | +| test.c:204:17:204:17 | a | 3 | +| test.c:204:33:204:33 | b | -2147483648 | +| test.c:204:38:204:38 | b | 0 | +| test.c:205:13:205:13 | a | 3 | +| test.c:205:15:205:15 | b | 0 | +| test.c:206:5:206:9 | total | -2147483648 | +| test.c:206:14:206:14 | r | -2147483648 | +| test.c:208:12:208:12 | a | -2147483648 | +| test.c:208:17:208:17 | a | 3 | +| test.c:208:35:208:35 | b | -2147483648 | +| test.c:208:40:208:40 | b | -13 | +| test.c:209:13:209:13 | a | 3 | +| test.c:209:15:209:15 | b | -13 | +| test.c:210:5:210:9 | total | -2147483648 | +| test.c:210:14:210:14 | r | -2147483648 | +| test.c:212:12:212:12 | a | -2147483648 | +| test.c:212:17:212:17 | a | 3 | +| test.c:212:35:212:35 | b | -2147483648 | +| test.c:212:40:212:40 | b | -13 | +| test.c:213:13:213:13 | a | 3 | +| test.c:213:15:213:15 | b | -13 | +| test.c:214:5:214:9 | total | -2147483648 | +| test.c:214:14:214:14 | r | -2147483648 | +| test.c:216:12:216:12 | a | -2147483648 | +| test.c:216:17:216:17 | a | 3 | +| test.c:216:35:216:35 | b | -2147483648 | +| test.c:216:40:216:40 | b | -13 | +| test.c:217:13:217:13 | a | 3 | +| test.c:217:15:217:15 | b | -13 | +| test.c:218:5:218:9 | total | -2147483648 | +| test.c:218:14:218:14 | r | -2147483648 | +| test.c:221:10:221:14 | total | -2147483648 | +| test.c:228:12:228:12 | a | -2147483648 | +| test.c:228:17:228:17 | a | 0 | +| test.c:228:33:228:33 | b | -2147483648 | +| test.c:228:38:228:38 | b | 5 | +| test.c:229:13:229:13 | a | 0 | +| test.c:229:15:229:15 | b | 5 | +| test.c:230:5:230:9 | total | 0 | +| test.c:230:14:230:14 | r | -2147483648 | +| test.c:232:12:232:12 | a | -2147483648 | +| test.c:232:17:232:17 | a | 0 | +| test.c:232:33:232:33 | b | -2147483648 | +| test.c:232:38:232:38 | b | 0 | +| test.c:233:13:233:13 | a | 0 | +| test.c:233:15:233:15 | b | 0 | +| test.c:234:5:234:9 | total | -2147483648 | +| test.c:234:14:234:14 | r | -2147483648 | +| test.c:236:12:236:12 | a | -2147483648 | +| test.c:236:17:236:17 | a | 0 | +| test.c:236:35:236:35 | b | -2147483648 | +| test.c:236:40:236:40 | b | -13 | +| test.c:237:13:237:13 | a | 0 | +| test.c:237:15:237:15 | b | -13 | +| test.c:238:5:238:9 | total | -2147483648 | +| test.c:238:14:238:14 | r | -2147483648 | +| test.c:240:12:240:12 | a | -2147483648 | +| test.c:240:17:240:17 | a | 0 | +| test.c:240:35:240:35 | b | -2147483648 | +| test.c:240:40:240:40 | b | -13 | +| test.c:241:13:241:13 | a | 0 | +| test.c:241:15:241:15 | b | -13 | +| test.c:242:5:242:9 | total | -2147483648 | +| test.c:242:14:242:14 | r | -2147483648 | +| test.c:244:12:244:12 | a | -2147483648 | +| test.c:244:17:244:17 | a | 0 | +| test.c:244:35:244:35 | b | -2147483648 | +| test.c:244:40:244:40 | b | -13 | +| test.c:245:13:245:13 | a | 0 | +| test.c:245:15:245:15 | b | -13 | +| test.c:246:5:246:9 | total | -2147483648 | +| test.c:246:14:246:14 | r | -2147483648 | +| test.c:249:10:249:14 | total | -2147483648 | +| test.c:256:14:256:14 | a | -2147483648 | +| test.c:256:19:256:19 | a | -17 | +| test.c:256:35:256:35 | b | -2147483648 | +| test.c:256:40:256:40 | b | 5 | +| test.c:257:13:257:13 | a | -17 | +| test.c:257:15:257:15 | b | 5 | +| test.c:258:5:258:9 | total | 0 | +| test.c:258:14:258:14 | r | -2147483648 | +| test.c:260:14:260:14 | a | -2147483648 | +| test.c:260:19:260:19 | a | -17 | +| test.c:260:35:260:35 | b | -2147483648 | +| test.c:260:40:260:40 | b | 0 | +| test.c:261:13:261:13 | a | -17 | +| test.c:261:15:261:15 | b | 0 | +| test.c:262:5:262:9 | total | -2147483648 | +| test.c:262:14:262:14 | r | -2147483648 | +| test.c:264:14:264:14 | a | -2147483648 | +| test.c:264:19:264:19 | a | -17 | +| test.c:264:37:264:37 | b | -2147483648 | +| test.c:264:42:264:42 | b | -13 | +| test.c:265:13:265:13 | a | -17 | +| test.c:265:15:265:15 | b | -13 | +| test.c:266:5:266:9 | total | -2147483648 | +| test.c:266:14:266:14 | r | -2147483648 | +| test.c:268:14:268:14 | a | -2147483648 | +| test.c:268:19:268:19 | a | -17 | +| test.c:268:37:268:37 | b | -2147483648 | +| test.c:268:42:268:42 | b | -13 | +| test.c:269:13:269:13 | a | -17 | +| test.c:269:15:269:15 | b | -13 | +| test.c:270:5:270:9 | total | -2147483648 | +| test.c:270:14:270:14 | r | -2147483648 | +| test.c:272:14:272:14 | a | -2147483648 | +| test.c:272:19:272:19 | a | -17 | +| test.c:272:37:272:37 | b | -2147483648 | +| test.c:272:42:272:42 | b | -13 | +| test.c:273:13:273:13 | a | -17 | +| test.c:273:15:273:15 | b | -13 | +| test.c:274:5:274:9 | total | -2147483648 | +| test.c:274:14:274:14 | r | -2147483648 | +| test.c:277:10:277:14 | total | -2147483648 | +| test.c:284:14:284:14 | a | -2147483648 | +| test.c:284:19:284:19 | a | -17 | +| test.c:284:34:284:34 | b | -2147483648 | +| test.c:284:39:284:39 | b | 5 | +| test.c:285:13:285:13 | a | -17 | +| test.c:285:15:285:15 | b | 5 | +| test.c:286:5:286:9 | total | 0 | +| test.c:286:14:286:14 | r | -2147483648 | +| test.c:288:14:288:14 | a | -2147483648 | +| test.c:288:19:288:19 | a | -17 | +| test.c:288:34:288:34 | b | -2147483648 | +| test.c:288:39:288:39 | b | 0 | +| test.c:289:13:289:13 | a | -17 | +| test.c:289:15:289:15 | b | 0 | +| test.c:290:5:290:9 | total | -2147483648 | +| test.c:290:14:290:14 | r | -2147483648 | +| test.c:292:14:292:14 | a | -2147483648 | +| test.c:292:19:292:19 | a | -17 | +| test.c:292:36:292:36 | b | -2147483648 | +| test.c:292:41:292:41 | b | -13 | +| test.c:293:13:293:13 | a | -17 | +| test.c:293:15:293:15 | b | -13 | +| test.c:294:5:294:9 | total | -2147483648 | +| test.c:294:14:294:14 | r | -2147483648 | +| test.c:296:14:296:14 | a | -2147483648 | +| test.c:296:19:296:19 | a | -17 | +| test.c:296:36:296:36 | b | -2147483648 | +| test.c:296:41:296:41 | b | -13 | +| test.c:297:13:297:13 | a | -17 | +| test.c:297:15:297:15 | b | -13 | +| test.c:298:5:298:9 | total | -2147483648 | +| test.c:298:14:298:14 | r | -2147483648 | +| test.c:300:14:300:14 | a | -2147483648 | +| test.c:300:19:300:19 | a | -17 | +| test.c:300:36:300:36 | b | -2147483648 | +| test.c:300:41:300:41 | b | -13 | +| test.c:301:13:301:13 | a | -17 | +| test.c:301:15:301:15 | b | -13 | +| test.c:302:5:302:9 | total | -2147483648 | +| test.c:302:14:302:14 | r | -2147483648 | +| test.c:305:10:305:14 | total | -2147483648 | +| test.c:312:14:312:14 | a | -2147483648 | +| test.c:312:19:312:19 | a | -17 | +| test.c:312:35:312:35 | b | -2147483648 | +| test.c:312:40:312:40 | b | 5 | +| test.c:313:13:313:13 | a | -17 | +| test.c:313:15:313:15 | b | 5 | +| test.c:314:5:314:9 | total | 0 | +| test.c:314:14:314:14 | r | -2147483648 | +| test.c:316:14:316:14 | a | -2147483648 | +| test.c:316:19:316:19 | a | -17 | +| test.c:316:35:316:35 | b | -2147483648 | +| test.c:316:40:316:40 | b | 0 | +| test.c:317:13:317:13 | a | -17 | +| test.c:317:15:317:15 | b | 0 | +| test.c:318:5:318:9 | total | -2147483648 | +| test.c:318:14:318:14 | r | -2147483648 | +| test.c:320:14:320:14 | a | -2147483648 | +| test.c:320:19:320:19 | a | -17 | +| test.c:320:37:320:37 | b | -2147483648 | +| test.c:320:42:320:42 | b | -13 | +| test.c:321:13:321:13 | a | -17 | +| test.c:321:15:321:15 | b | -13 | +| test.c:322:5:322:9 | total | -2147483648 | +| test.c:322:14:322:14 | r | -2147483648 | +| test.c:324:14:324:14 | a | -2147483648 | +| test.c:324:19:324:19 | a | -17 | +| test.c:324:37:324:37 | b | -2147483648 | +| test.c:324:42:324:42 | b | -13 | +| test.c:325:13:325:13 | a | -17 | +| test.c:325:15:325:15 | b | -13 | +| test.c:326:5:326:9 | total | -2147483648 | +| test.c:326:14:326:14 | r | -2147483648 | +| test.c:328:14:328:14 | a | -2147483648 | +| test.c:328:19:328:19 | a | -17 | +| test.c:328:37:328:37 | b | -2147483648 | +| test.c:328:42:328:42 | b | -13 | +| test.c:329:13:329:13 | a | -17 | +| test.c:329:15:329:15 | b | -13 | +| test.c:330:5:330:9 | total | -2147483648 | +| test.c:330:14:330:14 | r | -2147483648 | +| test.c:333:10:333:14 | total | -2147483648 | +| test.c:338:7:338:7 | x | -2147483648 | +| test.c:342:10:342:10 | i | 0 | +| test.c:343:5:343:5 | i | 0 | +| test.c:345:3:345:3 | d | -2147483648 | +| test.c:345:7:345:7 | i | 3 | +| test.c:346:7:346:7 | x | 0 | +| test.c:347:9:347:9 | d | 3 | +| test.c:347:14:347:14 | x | 0 | +| test.c:357:3:357:4 | y1 | 0 | +| test.c:357:8:357:8 | x | 0 | +| test.c:357:18:357:18 | x | 0 | +| test.c:358:3:358:4 | y2 | 0 | +| test.c:358:8:358:8 | x | 0 | +| test.c:358:24:358:24 | x | 0 | +| test.c:359:3:359:4 | y3 | 0 | +| test.c:360:3:360:4 | y4 | 0 | +| test.c:361:3:361:4 | y5 | 0 | +| test.c:362:3:362:4 | y6 | 0 | +| test.c:363:3:363:4 | y7 | 0 | +| test.c:364:3:364:4 | y8 | 0 | +| test.c:365:7:365:7 | x | 0 | +| test.c:366:5:366:6 | y3 | 0 | +| test.c:366:10:366:10 | x | 0 | +| test.c:367:5:367:6 | y4 | 0 | +| test.c:367:10:367:10 | x | 0 | +| test.c:368:5:368:6 | y5 | 0 | +| test.c:368:11:368:11 | x | 0 | +| test.c:369:5:369:6 | y6 | 0 | +| test.c:369:27:369:27 | x | 0 | +| test.c:370:5:370:6 | y7 | 0 | +| test.c:370:27:370:27 | x | 0 | +| test.c:371:5:371:6 | y8 | 0 | +| test.c:371:28:371:28 | x | 0 | +| test.c:373:10:373:11 | y1 | 0 | +| test.c:373:15:373:16 | y2 | 0 | +| test.c:373:20:373:21 | y3 | 0 | +| test.c:373:25:373:26 | y4 | 0 | +| test.c:373:30:373:31 | y5 | 0 | +| test.c:373:35:373:36 | y6 | 0 | +| test.c:373:40:373:41 | y7 | 0 | +| test.c:373:45:373:46 | y8 | 0 | +| test.c:379:3:379:4 | y1 | 0 | +| test.c:379:8:379:8 | x | 0 | +| test.c:379:18:379:18 | x | 101 | +| test.c:380:3:380:4 | y2 | 0 | +| test.c:380:8:380:8 | x | 0 | +| test.c:380:25:380:25 | x | 101 | +| test.c:381:3:381:4 | y3 | 0 | +| test.c:382:3:382:4 | y4 | 0 | +| test.c:383:3:383:4 | y5 | 0 | +| test.c:384:7:384:7 | x | 0 | +| test.c:385:5:385:6 | y3 | 0 | +| test.c:385:11:385:11 | x | 300 | +| test.c:386:5:386:6 | y4 | 0 | +| test.c:386:11:386:11 | x | 300 | +| test.c:387:5:387:6 | y5 | 0 | +| test.c:387:27:387:27 | x | 300 | +| test.c:389:10:389:11 | y1 | 101 | +| test.c:389:15:389:16 | y2 | 101 | +| test.c:389:20:389:21 | y3 | 0 | +| test.c:389:25:389:26 | y4 | 100 | +| test.c:389:30:389:31 | y5 | 0 | +| test.c:394:20:394:20 | x | 0 | +| test.c:394:30:394:30 | x | 0 | +| test.c:397:3:397:4 | y1 | 0 | +| test.c:397:11:397:11 | y | 0 | +| test.c:397:14:397:14 | y | 1 | +| test.c:398:3:398:4 | y2 | 0 | +| test.c:398:9:398:9 | y | 1 | +| test.c:398:14:398:14 | y | 2 | +| test.c:398:22:398:22 | y | 5 | +| test.c:399:10:399:11 | y1 | 1 | +| test.c:399:15:399:16 | y2 | 5 | +| test.c:407:3:407:3 | i | -2147483648 | +| test.c:408:7:408:7 | i | 10 | +| test.c:410:3:410:3 | i | -2147483648 | +| test.c:411:3:411:3 | i | 10 | +| test.c:412:7:412:7 | i | 20 | +| test.c:414:3:414:3 | i | -2147483648 | +| test.c:415:3:415:3 | i | 40 | +| test.c:416:7:416:7 | i | 30 | +| test.c:418:3:418:3 | i | -2147483648 | +| test.c:418:7:418:7 | j | -2147483648 | +| test.c:419:7:419:7 | i | 40 | +| test.c:421:3:421:3 | i | -2147483648 | +| test.c:421:8:421:8 | j | 40 | +| test.c:422:7:422:7 | i | 50 | +| test.c:424:3:424:3 | i | -2147483648 | +| test.c:424:13:424:13 | j | 50 | +| test.c:425:7:425:7 | i | 60 | +| test.c:432:12:432:12 | a | 0 | +| test.c:432:17:432:17 | a | 3 | +| test.c:432:33:432:33 | b | 0 | +| test.c:432:38:432:38 | b | 5 | +| test.c:433:13:433:13 | a | 3 | +| test.c:433:15:433:15 | b | 5 | +| test.c:434:5:434:9 | total | 0 | +| test.c:434:14:434:14 | r | 15 | +| test.c:436:12:436:12 | a | 0 | +| test.c:436:17:436:17 | a | 3 | +| test.c:436:33:436:33 | b | 0 | +| test.c:436:38:436:38 | b | 0 | +| test.c:437:13:437:13 | a | 3 | +| test.c:437:15:437:15 | b | 0 | +| test.c:438:5:438:9 | total | 0 | +| test.c:438:14:438:14 | r | 0 | +| test.c:440:12:440:12 | a | 0 | +| test.c:440:17:440:17 | a | 3 | +| test.c:440:34:440:34 | b | 0 | +| test.c:440:39:440:39 | b | 13 | +| test.c:441:13:441:13 | a | 3 | +| test.c:441:15:441:15 | b | 13 | +| test.c:442:5:442:9 | total | 0 | +| test.c:442:14:442:14 | r | 39 | +| test.c:445:10:445:14 | total | 0 | +| test.c:451:12:451:12 | b | 0 | +| test.c:451:17:451:17 | b | 5 | +| test.c:452:16:452:16 | b | 5 | +| test.c:453:5:453:9 | total | 0 | +| test.c:453:14:453:14 | r | 55 | +| test.c:455:12:455:12 | b | 0 | +| test.c:455:17:455:17 | b | 0 | +| test.c:456:16:456:16 | b | 0 | +| test.c:457:5:457:9 | total | 0 | +| test.c:457:14:457:14 | r | 0 | +| test.c:459:13:459:13 | b | 0 | +| test.c:459:18:459:18 | b | 13 | +| test.c:460:16:460:16 | b | 13 | +| test.c:461:5:461:9 | total | 0 | +| test.c:461:14:461:14 | r | 143 | +| test.c:464:10:464:14 | total | 0 | +| test.c:469:3:469:3 | x | 0 | +| test.c:469:7:469:7 | y | 0 | +| test.c:470:3:470:4 | xy | 0 | +| 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 | 0 | +| test.c:477:3:477:3 | y | 0 | +| 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 | 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 | +| test.c:485:12:485:17 | result | 100 | +| test.c:487:7:487:8 | ul | 0 | +| 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 | +| test.cpp:18:30:18:30 | x | -2147483648 | +| test.cpp:19:10:19:11 | x0 | -128 | +| test.cpp:27:7:27:7 | y | -2147483648 | +| test.cpp:28:5:28:5 | x | -2147483648 | +| test.cpp:30:7:30:7 | y | -2147483648 | +| test.cpp:31:5:31:5 | x | -2147483648 | +| test.cpp:33:7:33:7 | y | -2147483648 | +| test.cpp:34:5:34:5 | x | -2147483648 | +| test.cpp:36:7:36:7 | y | -2147483648 | +| test.cpp:37:5:37:5 | x | -2147483648 | +| test.cpp:39:7:39:7 | y | -2147483648 | +| test.cpp:40:5:40:5 | x | -2147483648 | +| test.cpp:42:7:42:7 | y | -2147483648 | +| test.cpp:43:5:43:5 | x | -2147483648 | +| test.cpp:45:7:45:7 | y | -2147483648 | +| test.cpp:46:5:46:5 | x | -2147483648 | +| test.cpp:51:7:51:7 | x | -2147483648 | +| test.cpp:52:21:52:21 | x | 0 | +| test.cpp:53:5:53:5 | t | 0 | +| test.cpp:53:15:53:16 | xb | 0 | +| test.cpp:56:7:56:7 | x | -2147483648 | +| test.cpp:57:21:57:21 | x | 1 | +| test.cpp:58:5:58:5 | t | 0 | +| test.cpp:58:15:58:16 | xb | 1 | +| test.cpp:61:7:61:7 | x | -2147483648 | +| test.cpp:62:21:62:21 | x | -2147483648 | +| test.cpp:63:5:63:5 | t | 0 | +| test.cpp:63:15:63:16 | xb | 1 | +| test.cpp:66:19:66:19 | x | -2147483648 | +| test.cpp:67:3:67:3 | t | 0 | +| test.cpp:67:13:67:14 | xb | 0 | +| test.cpp:69:10:69:10 | b | 0 | +| test.cpp:69:21:69:21 | t | 0 | +| test.cpp:74:30:74:30 | c | 0 | +| test.cpp:74:34:74:34 | c | 0 | +| test.cpp:75:22:75:30 | c_times_2 | 0 | +| test.cpp:77:5:77:13 | c_times_2 | 0 | +| test.cpp:79:3:79:11 | c_times_2 | 0 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.ql b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.ql index 67da6367972..70c2d8590e9 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.ql @@ -1,4 +1,4 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis from VariableAccess expr -select expr, lowerBound(expr) +select expr, lowerBound(expr).toString() diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c index 537aee7961d..4f14415ae18 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c @@ -422,7 +422,7 @@ void test17() { out(i); // 50 i = 20 + (j -= 10); - out(i); // 60 [BUG: the analysis thinks it's 2^-31 .. 2^31-1] + out(i); // 60 } // Tests for unsigned multiplication. @@ -463,3 +463,73 @@ int test_unsigned_mult02(unsigned b) { return total; } + +unsigned long mult_rounding() { + unsigned long x, y, xy; + x = y = 1000000003UL; // 1e9 + 3 + xy = x * y; + return xy; // BUG: upper bound should be >= 1000000006000000009UL +} + +unsigned long mult_overflow() { + unsigned long x, y, xy; + x = 274177UL; + y = 67280421310721UL; + xy = x * y; + 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 + } + if (ul >= 10) { + unsigned long result = ul * ul; + return result; // lower bound is correctly 0 (overflow is possible) + } + 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; +} diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected index a124f87f6f8..23929ab3520 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected @@ -1,524 +1,575 @@ -| inline_assembly.c:10:3:10:3 | y | 4.294967295E9 | -| inline_assembly.c:12:29:12:29 | x | 0.0 | -| inline_assembly.c:12:32:12:32 | y | 1.0 | -| inline_assembly.c:16:25:16:25 | x | 0.0 | -| inline_assembly.c:16:35:16:35 | y | 1.0 | -| inline_assembly.c:21:29:21:29 | x | 4.294967295E9 | -| inline_assembly.c:21:32:21:32 | y | 4.294967295E9 | -| minmax.c:18:37:18:37 | x | 1.0 | -| minmax.c:18:40:18:40 | y | 2.0 | -| minmax.c:18:43:18:43 | z | 3.0 | -| minmax.c:20:2:20:2 | z | 2.147483647E9 | -| minmax.c:22:8:22:8 | x | 1.0 | -| minmax.c:22:14:22:14 | y | 2.0 | -| minmax.c:22:18:22:18 | t | 2.147483647E9 | -| minmax.c:22:22:22:22 | x | 1.0 | -| minmax.c:23:3:23:3 | t | 1.0 | -| minmax.c:26:37:26:37 | x | 1.0 | -| minmax.c:26:40:26:40 | y | 2.0 | -| minmax.c:26:43:26:43 | z | 1.0 | -| test.c:8:5:8:9 | count | 2.147483647E9 | -| test.c:8:13:8:17 | count | 2.147483647E9 | -| test.c:10:10:10:14 | count | 2.147483647E9 | -| test.c:16:5:16:9 | count | 2.147483647E9 | -| test.c:16:14:16:18 | count | 15.0 | -| test.c:18:10:18:14 | count | 15.0 | -| test.c:24:5:24:9 | count | 15.0 | -| test.c:25:5:25:9 | count | 2.147483647E9 | -| test.c:25:13:25:17 | count | 127.0 | -| test.c:27:10:27:14 | count | 15.0 | -| test.c:33:8:33:8 | i | 2.147483647E9 | -| test.c:33:15:33:15 | i | 2.0 | -| test.c:33:22:33:22 | i | 2.147483647E9 | -| test.c:33:26:33:26 | i | 1.0 | -| test.c:34:5:34:9 | total | 2.147483647E9 | -| test.c:34:14:34:14 | i | 1.0 | -| test.c:36:10:36:14 | total | 2.147483647E9 | -| test.c:36:18:36:18 | i | 2.0 | -| test.c:42:8:42:8 | i | 2.147483647E9 | -| test.c:42:15:42:15 | i | 2.0 | -| test.c:42:22:42:22 | i | 1.0 | -| test.c:43:5:43:9 | total | 2.147483647E9 | -| test.c:43:14:43:14 | i | 1.0 | -| test.c:45:10:45:14 | total | 2.147483647E9 | -| test.c:45:18:45:18 | i | 2.0 | -| test.c:51:8:51:8 | i | 2.147483647E9 | -| test.c:51:15:51:15 | i | 2.0 | -| test.c:51:24:51:24 | i | 2.147483647E9 | -| test.c:51:28:51:28 | i | 1.0 | -| test.c:52:5:52:9 | total | 2.147483647E9 | -| test.c:52:14:52:14 | i | 1.0 | -| test.c:54:10:54:14 | total | 2.147483647E9 | -| test.c:54:18:54:18 | i | 2.0 | -| test.c:58:7:58:7 | i | 2.147483647E9 | -| test.c:59:9:59:9 | i | 3.0 | -| test.c:60:14:60:14 | i | 3.0 | -| test.c:67:15:67:15 | y | 2.147483647E9 | -| test.c:67:20:67:20 | y | 2.147483647E9 | -| test.c:68:9:68:9 | x | 2.147483647E9 | -| test.c:68:13:68:13 | y | 9.0 | -| test.c:69:14:69:14 | x | 6.0 | -| test.c:72:10:72:10 | y | 2.147483647E9 | -| test.c:76:7:76:7 | y | 2.147483647E9 | -| test.c:77:9:77:9 | x | 2.147483647E9 | -| test.c:81:9:81:9 | x | 2.147483647E9 | -| test.c:85:10:85:10 | x | 2.147483647E9 | -| test.c:89:7:89:7 | y | 2.147483647E9 | -| test.c:90:9:90:9 | x | 2.147483647E9 | -| test.c:90:13:90:13 | y | 2.147483647E9 | -| test.c:93:12:93:12 | x | 2.147483647E9 | -| test.c:100:3:100:3 | c | 127.0 | -| test.c:101:7:101:7 | c | 127.0 | -| test.c:104:7:104:7 | c | 127.0 | -| test.c:105:5:105:5 | c | 127.0 | -| test.c:106:9:106:9 | c | 127.0 | -| test.c:109:9:109:9 | c | 127.0 | -| test.c:119:10:119:10 | n | 1.8446744073709552E19 | -| test.c:124:11:124:15 | Start | 1.8446744073709552E19 | -| test.c:127:6:127:10 | Start | 1.8446744073709552E19 | -| test.c:127:15:127:20 | Length | 1.8446744073709552E19 | -| test.c:135:22:135:22 | c | 127.0 | -| test.c:137:20:137:20 | x | 0.0 | -| test.c:138:11:138:11 | i | 2.147483647E9 | -| test.c:139:19:139:19 | c | 127.0 | -| test.c:139:23:139:23 | i | 2.147483647E9 | -| test.c:139:27:139:28 | uc | 255.0 | -| test.c:139:32:139:32 | x | 0.0 | -| test.c:139:36:139:36 | y | 4.294967295E9 | -| test.c:139:40:139:40 | z | 2.147483647E9 | -| test.c:144:23:144:23 | x | 2.147483647E9 | -| test.c:145:32:145:32 | x | 2.147483647E9 | -| test.c:146:33:146:33 | x | 2.147483647E9 | -| test.c:147:31:147:31 | x | 2.147483647E9 | -| test.c:148:13:148:13 | x | 2.147483647E9 | -| test.c:149:23:149:23 | x | 2.147483647E9 | -| test.c:150:10:150:11 | x0 | 127.0 | -| test.c:150:15:150:16 | x1 | 255.0 | -| test.c:150:20:150:21 | x2 | 65535.0 | -| test.c:150:25:150:26 | x3 | 2.147483647E9 | -| test.c:150:30:150:31 | c0 | 127.0 | -| test.c:150:35:150:36 | s0 | 65535.0 | -| test.c:154:11:154:11 | x | 9.223372036854776E18 | -| test.c:154:20:154:20 | x | 9.223372036854776E18 | -| test.c:154:30:154:30 | x | 9.223372036854776E18 | -| test.c:154:35:154:35 | x | 2.147483647E9 | -| test.c:161:12:161:12 | a | 2.147483647E9 | -| test.c:161:17:161:17 | a | 2.147483647E9 | -| test.c:162:14:162:14 | a | 11.0 | -| test.c:163:14:163:14 | a | 11.0 | -| test.c:164:5:164:9 | total | 0.0 | -| test.c:164:14:164:14 | b | 11.0 | -| test.c:164:16:164:16 | c | -3.0 | -| test.c:166:12:166:12 | a | 2.147483647E9 | -| test.c:166:17:166:17 | a | 2.147483647E9 | -| test.c:167:14:167:14 | a | 11.0 | -| test.c:168:14:168:14 | a | 11.0 | -| test.c:169:5:169:9 | total | 8.0 | -| test.c:169:14:169:14 | b | 11.0 | -| test.c:169:16:169:16 | c | -0.0 | -| test.c:171:13:171:13 | a | 2.147483647E9 | -| test.c:171:18:171:18 | a | 2.147483647E9 | -| test.c:172:14:172:14 | a | 11.0 | -| test.c:173:14:173:14 | a | 11.0 | -| test.c:174:5:174:9 | total | 19.0 | -| test.c:174:14:174:14 | b | 11.0 | -| test.c:174:16:174:16 | c | 7.0 | -| test.c:176:13:176:13 | a | 2.147483647E9 | -| test.c:176:18:176:18 | a | 2.147483647E9 | -| test.c:177:14:177:14 | a | 1.0 | -| test.c:178:14:178:14 | a | 1.0 | -| test.c:179:5:179:9 | total | 37.0 | -| test.c:179:14:179:14 | b | 1.0 | -| test.c:179:16:179:16 | c | 7.0 | -| test.c:181:13:181:13 | a | 2.147483647E9 | -| test.c:181:18:181:18 | a | 2.147483647E9 | -| test.c:182:14:182:14 | a | 0.0 | -| test.c:183:14:183:14 | a | 0.0 | -| test.c:184:5:184:9 | total | 45.0 | -| test.c:184:14:184:14 | b | 0.0 | -| test.c:184:16:184:16 | c | 7.0 | -| test.c:186:13:186:13 | a | 2.147483647E9 | -| test.c:186:18:186:18 | a | 2.147483647E9 | -| test.c:187:14:187:14 | a | -2.0 | -| test.c:188:14:188:14 | a | -2.0 | -| test.c:189:5:189:9 | total | 52.0 | -| test.c:189:14:189:14 | b | -2.0 | -| test.c:189:16:189:16 | c | 7.0 | -| test.c:192:10:192:14 | total | 57.0 | -| test.c:200:12:200:12 | a | 2.147483647E9 | -| test.c:200:17:200:17 | a | 2.147483647E9 | -| test.c:200:33:200:33 | b | 2.147483647E9 | -| test.c:200:38:200:38 | b | 2.147483647E9 | -| test.c:201:13:201:13 | a | 11.0 | -| test.c:201:15:201:15 | b | 23.0 | -| test.c:202:5:202:9 | total | 0.0 | -| test.c:202:14:202:14 | r | 2.147483647E9 | -| test.c:204:12:204:12 | a | 2.147483647E9 | -| test.c:204:17:204:17 | a | 2.147483647E9 | -| test.c:204:33:204:33 | b | 2.147483647E9 | -| test.c:204:38:204:38 | b | 2.147483647E9 | -| test.c:205:13:205:13 | a | 11.0 | -| test.c:205:15:205:15 | b | 23.0 | -| test.c:206:5:206:9 | total | 2.147483647E9 | -| test.c:206:14:206:14 | r | 2.147483647E9 | -| test.c:208:12:208:12 | a | 2.147483647E9 | -| test.c:208:17:208:17 | a | 2.147483647E9 | -| test.c:208:35:208:35 | b | 2.147483647E9 | -| test.c:208:40:208:40 | b | 2.147483647E9 | -| test.c:209:13:209:13 | a | 11.0 | -| test.c:209:15:209:15 | b | 23.0 | -| test.c:210:5:210:9 | total | 2.147483647E9 | -| test.c:210:14:210:14 | r | 2.147483647E9 | -| test.c:212:12:212:12 | a | 2.147483647E9 | -| test.c:212:17:212:17 | a | 2.147483647E9 | -| test.c:212:35:212:35 | b | 2.147483647E9 | -| test.c:212:40:212:40 | b | 2.147483647E9 | -| test.c:213:13:213:13 | a | 11.0 | -| test.c:213:15:213:15 | b | 0.0 | -| test.c:214:5:214:9 | total | 2.147483647E9 | -| test.c:214:14:214:14 | r | 2.147483647E9 | -| test.c:216:12:216:12 | a | 2.147483647E9 | -| test.c:216:17:216:17 | a | 2.147483647E9 | -| test.c:216:35:216:35 | b | 2.147483647E9 | -| test.c:216:40:216:40 | b | 2.147483647E9 | -| test.c:217:13:217:13 | a | 11.0 | -| test.c:217:15:217:15 | b | -7.0 | -| test.c:218:5:218:9 | total | 2.147483647E9 | -| test.c:218:14:218:14 | r | 2.147483647E9 | -| test.c:221:10:221:14 | total | 2.147483647E9 | -| test.c:228:12:228:12 | a | 2.147483647E9 | -| test.c:228:17:228:17 | a | 2.147483647E9 | -| test.c:228:33:228:33 | b | 2.147483647E9 | -| test.c:228:38:228:38 | b | 2.147483647E9 | -| test.c:229:13:229:13 | a | 11.0 | -| test.c:229:15:229:15 | b | 23.0 | -| test.c:230:5:230:9 | total | 0.0 | -| test.c:230:14:230:14 | r | 2.147483647E9 | -| test.c:232:12:232:12 | a | 2.147483647E9 | -| test.c:232:17:232:17 | a | 2.147483647E9 | -| test.c:232:33:232:33 | b | 2.147483647E9 | -| test.c:232:38:232:38 | b | 2.147483647E9 | -| test.c:233:13:233:13 | a | 11.0 | -| test.c:233:15:233:15 | b | 23.0 | -| test.c:234:5:234:9 | total | 2.147483647E9 | -| test.c:234:14:234:14 | r | 2.147483647E9 | -| test.c:236:12:236:12 | a | 2.147483647E9 | -| test.c:236:17:236:17 | a | 2.147483647E9 | -| test.c:236:35:236:35 | b | 2.147483647E9 | -| test.c:236:40:236:40 | b | 2.147483647E9 | -| test.c:237:13:237:13 | a | 11.0 | -| test.c:237:15:237:15 | b | 23.0 | -| test.c:238:5:238:9 | total | 2.147483647E9 | -| test.c:238:14:238:14 | r | 2.147483647E9 | -| test.c:240:12:240:12 | a | 2.147483647E9 | -| test.c:240:17:240:17 | a | 2.147483647E9 | -| test.c:240:35:240:35 | b | 2.147483647E9 | -| test.c:240:40:240:40 | b | 2.147483647E9 | -| test.c:241:13:241:13 | a | 11.0 | -| test.c:241:15:241:15 | b | 0.0 | -| test.c:242:5:242:9 | total | 2.147483647E9 | -| test.c:242:14:242:14 | r | 2.147483647E9 | -| test.c:244:12:244:12 | a | 2.147483647E9 | -| test.c:244:17:244:17 | a | 2.147483647E9 | -| test.c:244:35:244:35 | b | 2.147483647E9 | -| test.c:244:40:244:40 | b | 2.147483647E9 | -| test.c:245:13:245:13 | a | 11.0 | -| test.c:245:15:245:15 | b | -7.0 | -| test.c:246:5:246:9 | total | 2.147483647E9 | -| test.c:246:14:246:14 | r | 2.147483647E9 | -| test.c:249:10:249:14 | total | 2.147483647E9 | -| test.c:256:14:256:14 | a | 2.147483647E9 | -| test.c:256:19:256:19 | a | 2.147483647E9 | -| test.c:256:35:256:35 | b | 2.147483647E9 | -| test.c:256:40:256:40 | b | 2.147483647E9 | -| test.c:257:13:257:13 | a | 11.0 | -| test.c:257:15:257:15 | b | 23.0 | -| test.c:258:5:258:9 | total | 0.0 | -| test.c:258:14:258:14 | r | 2.147483647E9 | -| test.c:260:14:260:14 | a | 2.147483647E9 | -| test.c:260:19:260:19 | a | 2.147483647E9 | -| test.c:260:35:260:35 | b | 2.147483647E9 | -| test.c:260:40:260:40 | b | 2.147483647E9 | -| test.c:261:13:261:13 | a | 11.0 | -| test.c:261:15:261:15 | b | 23.0 | -| test.c:262:5:262:9 | total | 2.147483647E9 | -| test.c:262:14:262:14 | r | 2.147483647E9 | -| test.c:264:14:264:14 | a | 2.147483647E9 | -| test.c:264:19:264:19 | a | 2.147483647E9 | -| test.c:264:37:264:37 | b | 2.147483647E9 | -| test.c:264:42:264:42 | b | 2.147483647E9 | -| test.c:265:13:265:13 | a | 11.0 | -| test.c:265:15:265:15 | b | 23.0 | -| test.c:266:5:266:9 | total | 2.147483647E9 | -| test.c:266:14:266:14 | r | 2.147483647E9 | -| test.c:268:14:268:14 | a | 2.147483647E9 | -| test.c:268:19:268:19 | a | 2.147483647E9 | -| test.c:268:37:268:37 | b | 2.147483647E9 | -| test.c:268:42:268:42 | b | 2.147483647E9 | -| test.c:269:13:269:13 | a | 11.0 | -| test.c:269:15:269:15 | b | 0.0 | -| test.c:270:5:270:9 | total | 2.147483647E9 | -| test.c:270:14:270:14 | r | 2.147483647E9 | -| test.c:272:14:272:14 | a | 2.147483647E9 | -| test.c:272:19:272:19 | a | 2.147483647E9 | -| test.c:272:37:272:37 | b | 2.147483647E9 | -| test.c:272:42:272:42 | b | 2.147483647E9 | -| test.c:273:13:273:13 | a | 11.0 | -| test.c:273:15:273:15 | b | -7.0 | -| test.c:274:5:274:9 | total | 2.147483647E9 | -| test.c:274:14:274:14 | r | 2.147483647E9 | -| test.c:277:10:277:14 | total | 2.147483647E9 | -| test.c:284:14:284:14 | a | 2.147483647E9 | -| test.c:284:19:284:19 | a | 2.147483647E9 | -| test.c:284:34:284:34 | b | 2.147483647E9 | -| test.c:284:39:284:39 | b | 2.147483647E9 | -| test.c:285:13:285:13 | a | 0.0 | -| test.c:285:15:285:15 | b | 23.0 | -| test.c:286:5:286:9 | total | 0.0 | -| test.c:286:14:286:14 | r | 2.147483647E9 | -| test.c:288:14:288:14 | a | 2.147483647E9 | -| test.c:288:19:288:19 | a | 2.147483647E9 | -| test.c:288:34:288:34 | b | 2.147483647E9 | -| test.c:288:39:288:39 | b | 2.147483647E9 | -| test.c:289:13:289:13 | a | 0.0 | -| test.c:289:15:289:15 | b | 23.0 | -| test.c:290:5:290:9 | total | 2.147483647E9 | -| test.c:290:14:290:14 | r | 2.147483647E9 | -| test.c:292:14:292:14 | a | 2.147483647E9 | -| test.c:292:19:292:19 | a | 2.147483647E9 | -| test.c:292:36:292:36 | b | 2.147483647E9 | -| test.c:292:41:292:41 | b | 2.147483647E9 | -| test.c:293:13:293:13 | a | 0.0 | -| test.c:293:15:293:15 | b | 23.0 | -| test.c:294:5:294:9 | total | 2.147483647E9 | -| test.c:294:14:294:14 | r | 2.147483647E9 | -| test.c:296:14:296:14 | a | 2.147483647E9 | -| test.c:296:19:296:19 | a | 2.147483647E9 | -| test.c:296:36:296:36 | b | 2.147483647E9 | -| test.c:296:41:296:41 | b | 2.147483647E9 | -| test.c:297:13:297:13 | a | 0.0 | -| test.c:297:15:297:15 | b | 0.0 | -| test.c:298:5:298:9 | total | 2.147483647E9 | -| test.c:298:14:298:14 | r | 2.147483647E9 | -| test.c:300:14:300:14 | a | 2.147483647E9 | -| test.c:300:19:300:19 | a | 2.147483647E9 | -| test.c:300:36:300:36 | b | 2.147483647E9 | -| test.c:300:41:300:41 | b | 2.147483647E9 | -| test.c:301:13:301:13 | a | 0.0 | -| test.c:301:15:301:15 | b | -7.0 | -| test.c:302:5:302:9 | total | 2.147483647E9 | -| test.c:302:14:302:14 | r | 2.147483647E9 | -| test.c:305:10:305:14 | total | 2.147483647E9 | -| test.c:312:14:312:14 | a | 2.147483647E9 | -| test.c:312:19:312:19 | a | 2.147483647E9 | -| test.c:312:35:312:35 | b | 2.147483647E9 | -| test.c:312:40:312:40 | b | 2.147483647E9 | -| test.c:313:13:313:13 | a | -2.0 | -| test.c:313:15:313:15 | b | 23.0 | -| test.c:314:5:314:9 | total | 0.0 | -| test.c:314:14:314:14 | r | 2.147483647E9 | -| test.c:316:14:316:14 | a | 2.147483647E9 | -| test.c:316:19:316:19 | a | 2.147483647E9 | -| test.c:316:35:316:35 | b | 2.147483647E9 | -| test.c:316:40:316:40 | b | 2.147483647E9 | -| test.c:317:13:317:13 | a | -2.0 | -| test.c:317:15:317:15 | b | 23.0 | -| test.c:318:5:318:9 | total | 2.147483647E9 | -| test.c:318:14:318:14 | r | 2.147483647E9 | -| test.c:320:14:320:14 | a | 2.147483647E9 | -| test.c:320:19:320:19 | a | 2.147483647E9 | -| test.c:320:37:320:37 | b | 2.147483647E9 | -| test.c:320:42:320:42 | b | 2.147483647E9 | -| test.c:321:13:321:13 | a | -2.0 | -| test.c:321:15:321:15 | b | 23.0 | -| test.c:322:5:322:9 | total | 2.147483647E9 | -| test.c:322:14:322:14 | r | 2.147483647E9 | -| test.c:324:14:324:14 | a | 2.147483647E9 | -| test.c:324:19:324:19 | a | 2.147483647E9 | -| test.c:324:37:324:37 | b | 2.147483647E9 | -| test.c:324:42:324:42 | b | 2.147483647E9 | -| test.c:325:13:325:13 | a | -2.0 | -| test.c:325:15:325:15 | b | 0.0 | -| test.c:326:5:326:9 | total | 2.147483647E9 | -| test.c:326:14:326:14 | r | 2.147483647E9 | -| test.c:328:14:328:14 | a | 2.147483647E9 | -| test.c:328:19:328:19 | a | 2.147483647E9 | -| test.c:328:37:328:37 | b | 2.147483647E9 | -| test.c:328:42:328:42 | b | 2.147483647E9 | -| test.c:329:13:329:13 | a | -2.0 | -| test.c:329:15:329:15 | b | -7.0 | -| test.c:330:5:330:9 | total | 2.147483647E9 | -| test.c:330:14:330:14 | r | 2.147483647E9 | -| test.c:333:10:333:14 | total | 2.147483647E9 | -| test.c:338:7:338:7 | x | 2.147483647E9 | -| test.c:342:10:342:10 | i | 7.0 | -| test.c:343:5:343:5 | i | 2.0 | -| test.c:345:3:345:3 | d | 2.147483647E9 | -| test.c:345:7:345:7 | i | 7.0 | -| test.c:346:7:346:7 | x | 2.147483647E9 | -| test.c:347:9:347:9 | d | 7.0 | -| test.c:347:14:347:14 | x | -1.0 | -| test.c:357:3:357:4 | y1 | 4.294967295E9 | -| test.c:357:8:357:8 | x | 4.294967295E9 | -| test.c:357:18:357:18 | x | 99.0 | -| test.c:358:3:358:4 | y2 | 4.294967295E9 | -| test.c:358:8:358:8 | x | 4.294967295E9 | -| test.c:358:24:358:24 | x | 99.0 | -| test.c:359:3:359:4 | y3 | 4.294967295E9 | -| test.c:360:3:360:4 | y4 | 4.294967295E9 | -| test.c:361:3:361:4 | y5 | 4.294967295E9 | -| test.c:362:3:362:4 | y6 | 4.294967295E9 | -| test.c:363:3:363:4 | y7 | 4.294967295E9 | -| test.c:364:3:364:4 | y8 | 4.294967295E9 | -| test.c:365:7:365:7 | x | 4.294967295E9 | -| test.c:366:5:366:6 | y3 | 4.294967295E9 | -| test.c:366:10:366:10 | x | 299.0 | -| test.c:367:5:367:6 | y4 | 4.294967295E9 | -| test.c:367:10:367:10 | x | 299.0 | -| test.c:368:5:368:6 | y5 | 4.294967295E9 | -| test.c:368:11:368:11 | x | 299.0 | -| test.c:369:5:369:6 | y6 | 4.294967295E9 | -| test.c:369:27:369:27 | x | 299.0 | -| test.c:370:5:370:6 | y7 | 4.294967295E9 | -| test.c:370:27:370:27 | x | 299.0 | -| test.c:371:5:371:6 | y8 | 4.294967295E9 | -| test.c:371:28:371:28 | x | 299.0 | -| test.c:373:10:373:11 | y1 | 99.0 | -| test.c:373:15:373:16 | y2 | 99.0 | -| test.c:373:20:373:21 | y3 | 299.0 | -| test.c:373:25:373:26 | y4 | 500.0 | -| test.c:373:30:373:31 | y5 | 300.0 | -| test.c:373:35:373:36 | y6 | 255.0 | -| test.c:373:40:373:41 | y7 | 500.0 | -| test.c:373:45:373:46 | y8 | 300.0 | -| test.c:379:3:379:4 | y1 | 4.294967295E9 | -| test.c:379:8:379:8 | x | 4.294967295E9 | -| test.c:379:18:379:18 | x | 4.294967295E9 | -| test.c:380:3:380:4 | y2 | 4.294967295E9 | -| test.c:380:8:380:8 | x | 4.294967295E9 | -| test.c:380:25:380:25 | x | 4.294967295E9 | -| test.c:381:3:381:4 | y3 | 4.294967295E9 | -| test.c:382:3:382:4 | y4 | 4.294967295E9 | -| test.c:383:3:383:4 | y5 | 4.294967295E9 | -| test.c:384:7:384:7 | x | 4.294967295E9 | -| test.c:385:5:385:6 | y3 | 4.294967295E9 | -| test.c:385:11:385:11 | x | 4.294967295E9 | -| test.c:386:5:386:6 | y4 | 4.294967295E9 | -| test.c:386:11:386:11 | x | 4.294967295E9 | -| test.c:387:5:387:6 | y5 | 4.294967295E9 | -| test.c:387:27:387:27 | x | 4.294967295E9 | -| test.c:389:10:389:11 | y1 | 4.294967295E9 | -| test.c:389:15:389:16 | y2 | 4.294967295E9 | -| test.c:389:20:389:21 | y3 | 4.294967295E9 | -| test.c:389:25:389:26 | y4 | 4.294967295E9 | -| test.c:389:30:389:31 | y5 | 1000.0 | -| test.c:394:20:394:20 | x | 4.294967295E9 | -| test.c:394:30:394:30 | x | 99.0 | -| test.c:397:3:397:4 | y1 | 4.294967295E9 | -| test.c:397:11:397:11 | y | 100.0 | -| test.c:397:14:397:14 | y | 101.0 | -| test.c:398:3:398:4 | y2 | 4.294967295E9 | -| test.c:398:9:398:9 | y | 101.0 | -| test.c:398:14:398:14 | y | 102.0 | -| test.c:398:22:398:22 | y | 105.0 | -| test.c:399:10:399:11 | y1 | 101.0 | -| test.c:399:15:399:16 | y2 | 105.0 | -| test.c:407:3:407:3 | i | 2.147483647E9 | -| test.c:408:7:408:7 | i | 10.0 | -| test.c:410:3:410:3 | i | 2.147483647E9 | -| test.c:411:3:411:3 | i | 10.0 | -| test.c:412:7:412:7 | i | 2.147483647E9 | -| test.c:414:3:414:3 | i | 2.147483647E9 | -| test.c:415:3:415:3 | i | 40.0 | -| test.c:416:7:416:7 | i | 2.147483647E9 | -| test.c:418:3:418:3 | i | 2.147483647E9 | -| test.c:418:7:418:7 | j | 2.147483647E9 | -| test.c:419:7:419:7 | i | 40.0 | -| test.c:421:3:421:3 | i | 2.147483647E9 | -| test.c:421:8:421:8 | j | 40.0 | -| test.c:422:7:422:7 | i | 50.0 | -| test.c:424:3:424:3 | i | 2.147483647E9 | -| test.c:424:13:424:13 | j | 2.147483647E9 | -| test.c:425:7:425:7 | i | 2.147483647E9 | -| test.c:432:12:432:12 | a | 4.294967295E9 | -| test.c:432:17:432:17 | a | 4.294967295E9 | -| test.c:432:33:432:33 | b | 4.294967295E9 | -| test.c:432:38:432:38 | b | 4.294967295E9 | -| test.c:433:13:433:13 | a | 11.0 | -| test.c:433:15:433:15 | b | 23.0 | -| test.c:434:5:434:9 | total | 0.0 | -| test.c:434:14:434:14 | r | 2.147483647E9 | -| test.c:436:12:436:12 | a | 4.294967295E9 | -| test.c:436:17:436:17 | a | 4.294967295E9 | -| test.c:436:33:436:33 | b | 4.294967295E9 | -| test.c:436:38:436:38 | b | 4.294967295E9 | -| test.c:437:13:437:13 | a | 11.0 | -| test.c:437:15:437:15 | b | 23.0 | -| test.c:438:5:438:9 | total | 2.147483647E9 | -| test.c:438:14:438:14 | r | 2.147483647E9 | -| test.c:440:12:440:12 | a | 4.294967295E9 | -| test.c:440:17:440:17 | a | 4.294967295E9 | -| test.c:440:34:440:34 | b | 4.294967295E9 | -| test.c:440:39:440:39 | b | 4.294967295E9 | -| test.c:441:13:441:13 | a | 11.0 | -| test.c:441:15:441:15 | b | 23.0 | -| test.c:442:5:442:9 | total | 2.147483647E9 | -| test.c:442:14:442:14 | r | 2.147483647E9 | -| test.c:445:10:445:14 | total | 2.147483647E9 | -| test.c:451:12:451:12 | b | 4.294967295E9 | -| test.c:451:17:451:17 | b | 4.294967295E9 | -| test.c:452:16:452:16 | b | 23.0 | -| test.c:453:5:453:9 | total | 0.0 | -| test.c:453:14:453:14 | r | 2.147483647E9 | -| test.c:455:12:455:12 | b | 4.294967295E9 | -| test.c:455:17:455:17 | b | 4.294967295E9 | -| test.c:456:16:456:16 | b | 23.0 | -| test.c:457:5:457:9 | total | 2.147483647E9 | -| test.c:457:14:457:14 | r | 2.147483647E9 | -| test.c:459:13:459:13 | b | 4.294967295E9 | -| test.c:459:18:459:18 | b | 4.294967295E9 | -| test.c:460:16:460:16 | b | 23.0 | -| test.c:461:5:461:9 | total | 2.147483647E9 | -| test.c:461:14:461:14 | r | 2.147483647E9 | -| test.c:464:10:464:14 | total | 2.147483647E9 | -| test.cpp:10:7:10:7 | b | 2.147483647E9 | -| test.cpp:11:5:11:5 | x | 2.147483647E9 | -| test.cpp:13:10:13:10 | x | 2.147483647E9 | -| test.cpp:18:30:18:30 | x | 2.147483647E9 | -| test.cpp:19:10:19:11 | x0 | 127.0 | -| test.cpp:27:7:27:7 | y | 2.147483647E9 | -| test.cpp:28:5:28:5 | x | 2.147483647E9 | -| test.cpp:30:7:30:7 | y | 2.147483647E9 | -| test.cpp:31:5:31:5 | x | 2.147483647E9 | -| test.cpp:33:7:33:7 | y | 2.147483647E9 | -| test.cpp:34:5:34:5 | x | 2.147483647E9 | -| test.cpp:36:7:36:7 | y | 2.147483647E9 | -| test.cpp:37:5:37:5 | x | 2.147483647E9 | -| test.cpp:39:7:39:7 | y | 2.147483647E9 | -| test.cpp:40:5:40:5 | x | 2.147483647E9 | -| test.cpp:42:7:42:7 | y | 2.147483647E9 | -| test.cpp:43:5:43:5 | x | 2.147483647E9 | -| test.cpp:45:7:45:7 | y | 2.147483647E9 | -| test.cpp:46:5:46:5 | x | 2.147483647E9 | -| test.cpp:51:7:51:7 | x | 2.147483647E9 | -| test.cpp:52:21:52:21 | x | 0.0 | -| test.cpp:53:5:53:5 | t | 0.0 | -| test.cpp:53:15:53:16 | xb | 0.0 | -| test.cpp:56:7:56:7 | x | 2.147483647E9 | -| test.cpp:57:21:57:21 | x | 2.147483647E9 | -| test.cpp:58:5:58:5 | t | 0.0 | -| test.cpp:58:15:58:16 | xb | 1.0 | -| test.cpp:61:7:61:7 | x | 2.147483647E9 | -| test.cpp:62:21:62:21 | x | -1.0 | -| test.cpp:63:5:63:5 | t | 1.0 | -| test.cpp:63:15:63:16 | xb | 1.0 | -| test.cpp:66:19:66:19 | x | 2.147483647E9 | -| test.cpp:67:3:67:3 | t | 2.0 | -| test.cpp:67:13:67:14 | xb | 1.0 | -| test.cpp:69:10:69:10 | b | 1.0 | -| test.cpp:69:21:69:21 | t | 3.0 | -| test.cpp:74:30:74:30 | c | 255.0 | -| test.cpp:74:34:74:34 | c | 255.0 | -| test.cpp:75:22:75:30 | c_times_2 | 510.0 | -| test.cpp:77:5:77:13 | c_times_2 | 510.0 | -| test.cpp:79:3:79:11 | c_times_2 | 510.0 | +| inline_assembly.c:10:3:10:3 | y | 4294967295 | +| inline_assembly.c:12:29:12:29 | x | 0 | +| inline_assembly.c:12:32:12:32 | y | 1 | +| inline_assembly.c:16:25:16:25 | x | 0 | +| inline_assembly.c:16:35:16:35 | y | 1 | +| inline_assembly.c:21:29:21:29 | x | 4294967295 | +| inline_assembly.c:21:32:21:32 | y | 4294967295 | +| minmax.c:18:37:18:37 | x | 1 | +| minmax.c:18:40:18:40 | y | 2 | +| minmax.c:18:43:18:43 | z | 3 | +| minmax.c:20:2:20:2 | z | 2147483647 | +| minmax.c:22:8:22:8 | x | 1 | +| minmax.c:22:14:22:14 | y | 2 | +| minmax.c:22:18:22:18 | t | 2147483647 | +| minmax.c:22:22:22:22 | x | 1 | +| minmax.c:23:3:23:3 | t | 1 | +| minmax.c:26:37:26:37 | x | 1 | +| minmax.c:26:40:26:40 | y | 2 | +| minmax.c:26:43:26:43 | z | 1 | +| test.c:8:5:8:9 | count | 2147483647 | +| test.c:8:13:8:17 | count | 2147483647 | +| test.c:10:10:10:14 | count | 2147483647 | +| test.c:16:5:16:9 | count | 2147483647 | +| test.c:16:14:16:18 | count | 15 | +| test.c:18:10:18:14 | count | 15 | +| test.c:24:5:24:9 | count | 15 | +| test.c:25:5:25:9 | count | 2147483647 | +| test.c:25:13:25:17 | count | 127 | +| test.c:27:10:27:14 | count | 15 | +| test.c:33:8:33:8 | i | 2147483647 | +| test.c:33:15:33:15 | i | 2 | +| test.c:33:22:33:22 | i | 2147483647 | +| test.c:33:26:33:26 | i | 1 | +| test.c:34:5:34:9 | total | 2147483647 | +| test.c:34:14:34:14 | i | 1 | +| test.c:36:10:36:14 | total | 2147483647 | +| test.c:36:18:36:18 | i | 2 | +| test.c:42:8:42:8 | i | 2147483647 | +| test.c:42:15:42:15 | i | 2 | +| test.c:42:22:42:22 | i | 1 | +| test.c:43:5:43:9 | total | 2147483647 | +| test.c:43:14:43:14 | i | 1 | +| test.c:45:10:45:14 | total | 2147483647 | +| test.c:45:18:45:18 | i | 2 | +| test.c:51:8:51:8 | i | 2147483647 | +| test.c:51:15:51:15 | i | 2 | +| test.c:51:24:51:24 | i | 2147483647 | +| test.c:51:28:51:28 | i | 1 | +| test.c:52:5:52:9 | total | 2147483647 | +| test.c:52:14:52:14 | i | 1 | +| test.c:54:10:54:14 | total | 2147483647 | +| test.c:54:18:54:18 | i | 2 | +| test.c:58:7:58:7 | i | 2147483647 | +| test.c:59:9:59:9 | i | 3 | +| test.c:60:14:60:14 | i | 3 | +| test.c:67:15:67:15 | y | 2147483647 | +| test.c:67:20:67:20 | y | 2147483647 | +| test.c:68:9:68:9 | x | 2147483647 | +| test.c:68:13:68:13 | y | 9 | +| test.c:69:14:69:14 | x | 6 | +| test.c:72:10:72:10 | y | 2147483647 | +| test.c:76:7:76:7 | y | 2147483647 | +| test.c:77:9:77:9 | x | 2147483647 | +| test.c:81:9:81:9 | x | 2147483647 | +| test.c:85:10:85:10 | x | 2147483647 | +| test.c:89:7:89:7 | y | 2147483647 | +| test.c:90:9:90:9 | x | 2147483647 | +| test.c:90:13:90:13 | y | 2147483647 | +| test.c:93:12:93:12 | x | 2147483647 | +| test.c:100:3:100:3 | c | 127 | +| test.c:101:7:101:7 | c | 127 | +| test.c:104:7:104:7 | c | 127 | +| 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 | 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 | +| test.c:139:19:139:19 | c | 127 | +| test.c:139:23:139:23 | i | 2147483647 | +| test.c:139:27:139:28 | uc | 255 | +| test.c:139:32:139:32 | x | 0 | +| test.c:139:36:139:36 | y | 4294967295 | +| test.c:139:40:139:40 | z | 2147483647 | +| test.c:144:23:144:23 | x | 2147483647 | +| test.c:145:32:145:32 | x | 2147483647 | +| test.c:146:33:146:33 | x | 2147483647 | +| test.c:147:31:147:31 | x | 2147483647 | +| test.c:148:13:148:13 | x | 2147483647 | +| test.c:149:23:149:23 | x | 2147483647 | +| test.c:150:10:150:11 | x0 | 127 | +| test.c:150:15:150:16 | x1 | 255 | +| test.c:150:20:150:21 | x2 | 65535 | +| 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 | 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 | +| test.c:162:14:162:14 | a | 11 | +| test.c:163:14:163:14 | a | 11 | +| test.c:164:5:164:9 | total | 0 | +| test.c:164:14:164:14 | b | 11 | +| test.c:164:16:164:16 | c | -3 | +| test.c:166:12:166:12 | a | 2147483647 | +| test.c:166:17:166:17 | a | 2147483647 | +| test.c:167:14:167:14 | a | 11 | +| test.c:168:14:168:14 | a | 11 | +| test.c:169:5:169:9 | total | 8 | +| test.c:169:14:169:14 | b | 11 | +| test.c:169:16:169:16 | c | -0 | +| test.c:171:13:171:13 | a | 2147483647 | +| test.c:171:18:171:18 | a | 2147483647 | +| test.c:172:14:172:14 | a | 11 | +| test.c:173:14:173:14 | a | 11 | +| test.c:174:5:174:9 | total | 19 | +| test.c:174:14:174:14 | b | 11 | +| test.c:174:16:174:16 | c | 7 | +| test.c:176:13:176:13 | a | 2147483647 | +| test.c:176:18:176:18 | a | 2147483647 | +| test.c:177:14:177:14 | a | 1 | +| test.c:178:14:178:14 | a | 1 | +| test.c:179:5:179:9 | total | 37 | +| test.c:179:14:179:14 | b | 1 | +| test.c:179:16:179:16 | c | 7 | +| test.c:181:13:181:13 | a | 2147483647 | +| test.c:181:18:181:18 | a | 2147483647 | +| test.c:182:14:182:14 | a | 0 | +| test.c:183:14:183:14 | a | 0 | +| test.c:184:5:184:9 | total | 45 | +| test.c:184:14:184:14 | b | 0 | +| test.c:184:16:184:16 | c | 7 | +| test.c:186:13:186:13 | a | 2147483647 | +| test.c:186:18:186:18 | a | 2147483647 | +| test.c:187:14:187:14 | a | -2 | +| test.c:188:14:188:14 | a | -2 | +| test.c:189:5:189:9 | total | 52 | +| test.c:189:14:189:14 | b | -2 | +| test.c:189:16:189:16 | c | 7 | +| test.c:192:10:192:14 | total | 57 | +| test.c:200:12:200:12 | a | 2147483647 | +| test.c:200:17:200:17 | a | 2147483647 | +| test.c:200:33:200:33 | b | 2147483647 | +| test.c:200:38:200:38 | b | 2147483647 | +| test.c:201:13:201:13 | a | 11 | +| test.c:201:15:201:15 | b | 23 | +| test.c:202:5:202:9 | total | 0 | +| test.c:202:14:202:14 | r | 2147483647 | +| test.c:204:12:204:12 | a | 2147483647 | +| test.c:204:17:204:17 | a | 2147483647 | +| test.c:204:33:204:33 | b | 2147483647 | +| test.c:204:38:204:38 | b | 2147483647 | +| test.c:205:13:205:13 | a | 11 | +| test.c:205:15:205:15 | b | 23 | +| test.c:206:5:206:9 | total | 2147483647 | +| test.c:206:14:206:14 | r | 2147483647 | +| test.c:208:12:208:12 | a | 2147483647 | +| test.c:208:17:208:17 | a | 2147483647 | +| test.c:208:35:208:35 | b | 2147483647 | +| test.c:208:40:208:40 | b | 2147483647 | +| test.c:209:13:209:13 | a | 11 | +| test.c:209:15:209:15 | b | 23 | +| test.c:210:5:210:9 | total | 2147483647 | +| test.c:210:14:210:14 | r | 2147483647 | +| test.c:212:12:212:12 | a | 2147483647 | +| test.c:212:17:212:17 | a | 2147483647 | +| test.c:212:35:212:35 | b | 2147483647 | +| test.c:212:40:212:40 | b | 2147483647 | +| test.c:213:13:213:13 | a | 11 | +| test.c:213:15:213:15 | b | 0 | +| test.c:214:5:214:9 | total | 2147483647 | +| test.c:214:14:214:14 | r | 2147483647 | +| test.c:216:12:216:12 | a | 2147483647 | +| test.c:216:17:216:17 | a | 2147483647 | +| test.c:216:35:216:35 | b | 2147483647 | +| test.c:216:40:216:40 | b | 2147483647 | +| test.c:217:13:217:13 | a | 11 | +| test.c:217:15:217:15 | b | -7 | +| test.c:218:5:218:9 | total | 2147483647 | +| test.c:218:14:218:14 | r | 2147483647 | +| test.c:221:10:221:14 | total | 2147483647 | +| test.c:228:12:228:12 | a | 2147483647 | +| test.c:228:17:228:17 | a | 2147483647 | +| test.c:228:33:228:33 | b | 2147483647 | +| test.c:228:38:228:38 | b | 2147483647 | +| test.c:229:13:229:13 | a | 11 | +| test.c:229:15:229:15 | b | 23 | +| test.c:230:5:230:9 | total | 0 | +| test.c:230:14:230:14 | r | 2147483647 | +| test.c:232:12:232:12 | a | 2147483647 | +| test.c:232:17:232:17 | a | 2147483647 | +| test.c:232:33:232:33 | b | 2147483647 | +| test.c:232:38:232:38 | b | 2147483647 | +| test.c:233:13:233:13 | a | 11 | +| test.c:233:15:233:15 | b | 23 | +| test.c:234:5:234:9 | total | 2147483647 | +| test.c:234:14:234:14 | r | 2147483647 | +| test.c:236:12:236:12 | a | 2147483647 | +| test.c:236:17:236:17 | a | 2147483647 | +| test.c:236:35:236:35 | b | 2147483647 | +| test.c:236:40:236:40 | b | 2147483647 | +| test.c:237:13:237:13 | a | 11 | +| test.c:237:15:237:15 | b | 23 | +| test.c:238:5:238:9 | total | 2147483647 | +| test.c:238:14:238:14 | r | 2147483647 | +| test.c:240:12:240:12 | a | 2147483647 | +| test.c:240:17:240:17 | a | 2147483647 | +| test.c:240:35:240:35 | b | 2147483647 | +| test.c:240:40:240:40 | b | 2147483647 | +| test.c:241:13:241:13 | a | 11 | +| test.c:241:15:241:15 | b | 0 | +| test.c:242:5:242:9 | total | 2147483647 | +| test.c:242:14:242:14 | r | 2147483647 | +| test.c:244:12:244:12 | a | 2147483647 | +| test.c:244:17:244:17 | a | 2147483647 | +| test.c:244:35:244:35 | b | 2147483647 | +| test.c:244:40:244:40 | b | 2147483647 | +| test.c:245:13:245:13 | a | 11 | +| test.c:245:15:245:15 | b | -7 | +| test.c:246:5:246:9 | total | 2147483647 | +| test.c:246:14:246:14 | r | 2147483647 | +| test.c:249:10:249:14 | total | 2147483647 | +| test.c:256:14:256:14 | a | 2147483647 | +| test.c:256:19:256:19 | a | 2147483647 | +| test.c:256:35:256:35 | b | 2147483647 | +| test.c:256:40:256:40 | b | 2147483647 | +| test.c:257:13:257:13 | a | 11 | +| test.c:257:15:257:15 | b | 23 | +| test.c:258:5:258:9 | total | 0 | +| test.c:258:14:258:14 | r | 2147483647 | +| test.c:260:14:260:14 | a | 2147483647 | +| test.c:260:19:260:19 | a | 2147483647 | +| test.c:260:35:260:35 | b | 2147483647 | +| test.c:260:40:260:40 | b | 2147483647 | +| test.c:261:13:261:13 | a | 11 | +| test.c:261:15:261:15 | b | 23 | +| test.c:262:5:262:9 | total | 2147483647 | +| test.c:262:14:262:14 | r | 2147483647 | +| test.c:264:14:264:14 | a | 2147483647 | +| test.c:264:19:264:19 | a | 2147483647 | +| test.c:264:37:264:37 | b | 2147483647 | +| test.c:264:42:264:42 | b | 2147483647 | +| test.c:265:13:265:13 | a | 11 | +| test.c:265:15:265:15 | b | 23 | +| test.c:266:5:266:9 | total | 2147483647 | +| test.c:266:14:266:14 | r | 2147483647 | +| test.c:268:14:268:14 | a | 2147483647 | +| test.c:268:19:268:19 | a | 2147483647 | +| test.c:268:37:268:37 | b | 2147483647 | +| test.c:268:42:268:42 | b | 2147483647 | +| test.c:269:13:269:13 | a | 11 | +| test.c:269:15:269:15 | b | 0 | +| test.c:270:5:270:9 | total | 2147483647 | +| test.c:270:14:270:14 | r | 2147483647 | +| test.c:272:14:272:14 | a | 2147483647 | +| test.c:272:19:272:19 | a | 2147483647 | +| test.c:272:37:272:37 | b | 2147483647 | +| test.c:272:42:272:42 | b | 2147483647 | +| test.c:273:13:273:13 | a | 11 | +| test.c:273:15:273:15 | b | -7 | +| test.c:274:5:274:9 | total | 2147483647 | +| test.c:274:14:274:14 | r | 2147483647 | +| test.c:277:10:277:14 | total | 2147483647 | +| test.c:284:14:284:14 | a | 2147483647 | +| test.c:284:19:284:19 | a | 2147483647 | +| test.c:284:34:284:34 | b | 2147483647 | +| test.c:284:39:284:39 | b | 2147483647 | +| test.c:285:13:285:13 | a | 0 | +| test.c:285:15:285:15 | b | 23 | +| test.c:286:5:286:9 | total | 0 | +| test.c:286:14:286:14 | r | 2147483647 | +| test.c:288:14:288:14 | a | 2147483647 | +| test.c:288:19:288:19 | a | 2147483647 | +| test.c:288:34:288:34 | b | 2147483647 | +| test.c:288:39:288:39 | b | 2147483647 | +| test.c:289:13:289:13 | a | 0 | +| test.c:289:15:289:15 | b | 23 | +| test.c:290:5:290:9 | total | 2147483647 | +| test.c:290:14:290:14 | r | 2147483647 | +| test.c:292:14:292:14 | a | 2147483647 | +| test.c:292:19:292:19 | a | 2147483647 | +| test.c:292:36:292:36 | b | 2147483647 | +| test.c:292:41:292:41 | b | 2147483647 | +| test.c:293:13:293:13 | a | 0 | +| test.c:293:15:293:15 | b | 23 | +| test.c:294:5:294:9 | total | 2147483647 | +| test.c:294:14:294:14 | r | 2147483647 | +| test.c:296:14:296:14 | a | 2147483647 | +| test.c:296:19:296:19 | a | 2147483647 | +| test.c:296:36:296:36 | b | 2147483647 | +| test.c:296:41:296:41 | b | 2147483647 | +| test.c:297:13:297:13 | a | 0 | +| test.c:297:15:297:15 | b | 0 | +| test.c:298:5:298:9 | total | 2147483647 | +| test.c:298:14:298:14 | r | 2147483647 | +| test.c:300:14:300:14 | a | 2147483647 | +| test.c:300:19:300:19 | a | 2147483647 | +| test.c:300:36:300:36 | b | 2147483647 | +| test.c:300:41:300:41 | b | 2147483647 | +| test.c:301:13:301:13 | a | 0 | +| test.c:301:15:301:15 | b | -7 | +| test.c:302:5:302:9 | total | 2147483647 | +| test.c:302:14:302:14 | r | 2147483647 | +| test.c:305:10:305:14 | total | 2147483647 | +| test.c:312:14:312:14 | a | 2147483647 | +| test.c:312:19:312:19 | a | 2147483647 | +| test.c:312:35:312:35 | b | 2147483647 | +| test.c:312:40:312:40 | b | 2147483647 | +| test.c:313:13:313:13 | a | -2 | +| test.c:313:15:313:15 | b | 23 | +| test.c:314:5:314:9 | total | 0 | +| test.c:314:14:314:14 | r | 2147483647 | +| test.c:316:14:316:14 | a | 2147483647 | +| test.c:316:19:316:19 | a | 2147483647 | +| test.c:316:35:316:35 | b | 2147483647 | +| test.c:316:40:316:40 | b | 2147483647 | +| test.c:317:13:317:13 | a | -2 | +| test.c:317:15:317:15 | b | 23 | +| test.c:318:5:318:9 | total | 2147483647 | +| test.c:318:14:318:14 | r | 2147483647 | +| test.c:320:14:320:14 | a | 2147483647 | +| test.c:320:19:320:19 | a | 2147483647 | +| test.c:320:37:320:37 | b | 2147483647 | +| test.c:320:42:320:42 | b | 2147483647 | +| test.c:321:13:321:13 | a | -2 | +| test.c:321:15:321:15 | b | 23 | +| test.c:322:5:322:9 | total | 2147483647 | +| test.c:322:14:322:14 | r | 2147483647 | +| test.c:324:14:324:14 | a | 2147483647 | +| test.c:324:19:324:19 | a | 2147483647 | +| test.c:324:37:324:37 | b | 2147483647 | +| test.c:324:42:324:42 | b | 2147483647 | +| test.c:325:13:325:13 | a | -2 | +| test.c:325:15:325:15 | b | 0 | +| test.c:326:5:326:9 | total | 2147483647 | +| test.c:326:14:326:14 | r | 2147483647 | +| test.c:328:14:328:14 | a | 2147483647 | +| test.c:328:19:328:19 | a | 2147483647 | +| test.c:328:37:328:37 | b | 2147483647 | +| test.c:328:42:328:42 | b | 2147483647 | +| test.c:329:13:329:13 | a | -2 | +| test.c:329:15:329:15 | b | -7 | +| test.c:330:5:330:9 | total | 2147483647 | +| test.c:330:14:330:14 | r | 2147483647 | +| test.c:333:10:333:14 | total | 2147483647 | +| test.c:338:7:338:7 | x | 2147483647 | +| test.c:342:10:342:10 | i | 7 | +| test.c:343:5:343:5 | i | 2 | +| test.c:345:3:345:3 | d | 2147483647 | +| test.c:345:7:345:7 | i | 7 | +| test.c:346:7:346:7 | x | 2147483647 | +| test.c:347:9:347:9 | d | 7 | +| test.c:347:14:347:14 | x | -1 | +| test.c:357:3:357:4 | y1 | 4294967295 | +| test.c:357:8:357:8 | x | 4294967295 | +| test.c:357:18:357:18 | x | 99 | +| test.c:358:3:358:4 | y2 | 4294967295 | +| test.c:358:8:358:8 | x | 4294967295 | +| test.c:358:24:358:24 | x | 99 | +| test.c:359:3:359:4 | y3 | 4294967295 | +| test.c:360:3:360:4 | y4 | 4294967295 | +| test.c:361:3:361:4 | y5 | 4294967295 | +| test.c:362:3:362:4 | y6 | 4294967295 | +| test.c:363:3:363:4 | y7 | 4294967295 | +| test.c:364:3:364:4 | y8 | 4294967295 | +| test.c:365:7:365:7 | x | 4294967295 | +| test.c:366:5:366:6 | y3 | 4294967295 | +| test.c:366:10:366:10 | x | 299 | +| test.c:367:5:367:6 | y4 | 4294967295 | +| test.c:367:10:367:10 | x | 299 | +| test.c:368:5:368:6 | y5 | 4294967295 | +| test.c:368:11:368:11 | x | 299 | +| test.c:369:5:369:6 | y6 | 4294967295 | +| test.c:369:27:369:27 | x | 299 | +| test.c:370:5:370:6 | y7 | 4294967295 | +| test.c:370:27:370:27 | x | 299 | +| test.c:371:5:371:6 | y8 | 4294967295 | +| test.c:371:28:371:28 | x | 299 | +| test.c:373:10:373:11 | y1 | 99 | +| test.c:373:15:373:16 | y2 | 99 | +| test.c:373:20:373:21 | y3 | 299 | +| test.c:373:25:373:26 | y4 | 500 | +| test.c:373:30:373:31 | y5 | 300 | +| test.c:373:35:373:36 | y6 | 255 | +| test.c:373:40:373:41 | y7 | 500 | +| test.c:373:45:373:46 | y8 | 300 | +| test.c:379:3:379:4 | y1 | 4294967295 | +| test.c:379:8:379:8 | x | 4294967295 | +| test.c:379:18:379:18 | x | 4294967295 | +| test.c:380:3:380:4 | y2 | 4294967295 | +| test.c:380:8:380:8 | x | 4294967295 | +| test.c:380:25:380:25 | x | 4294967295 | +| test.c:381:3:381:4 | y3 | 4294967295 | +| test.c:382:3:382:4 | y4 | 4294967295 | +| test.c:383:3:383:4 | y5 | 4294967295 | +| test.c:384:7:384:7 | x | 4294967295 | +| test.c:385:5:385:6 | y3 | 4294967295 | +| test.c:385:11:385:11 | x | 4294967295 | +| test.c:386:5:386:6 | y4 | 4294967295 | +| test.c:386:11:386:11 | x | 4294967295 | +| test.c:387:5:387:6 | y5 | 4294967295 | +| test.c:387:27:387:27 | x | 4294967295 | +| test.c:389:10:389:11 | y1 | 4294967295 | +| test.c:389:15:389:16 | y2 | 4294967295 | +| test.c:389:20:389:21 | y3 | 4294967295 | +| test.c:389:25:389:26 | y4 | 4294967295 | +| test.c:389:30:389:31 | y5 | 1000 | +| test.c:394:20:394:20 | x | 4294967295 | +| test.c:394:30:394:30 | x | 99 | +| test.c:397:3:397:4 | y1 | 4294967295 | +| test.c:397:11:397:11 | y | 100 | +| test.c:397:14:397:14 | y | 101 | +| test.c:398:3:398:4 | y2 | 4294967295 | +| test.c:398:9:398:9 | y | 101 | +| test.c:398:14:398:14 | y | 102 | +| test.c:398:22:398:22 | y | 105 | +| test.c:399:10:399:11 | y1 | 101 | +| test.c:399:15:399:16 | y2 | 105 | +| test.c:407:3:407:3 | i | 2147483647 | +| test.c:408:7:408:7 | i | 10 | +| test.c:410:3:410:3 | i | 2147483647 | +| test.c:411:3:411:3 | i | 10 | +| test.c:412:7:412:7 | i | 20 | +| test.c:414:3:414:3 | i | 2147483647 | +| test.c:415:3:415:3 | i | 40 | +| test.c:416:7:416:7 | i | 30 | +| test.c:418:3:418:3 | i | 2147483647 | +| test.c:418:7:418:7 | j | 2147483647 | +| test.c:419:7:419:7 | i | 40 | +| test.c:421:3:421:3 | i | 2147483647 | +| test.c:421:8:421:8 | j | 40 | +| test.c:422:7:422:7 | i | 50 | +| test.c:424:3:424:3 | i | 2147483647 | +| test.c:424:13:424:13 | j | 50 | +| test.c:425:7:425:7 | i | 60 | +| test.c:432:12:432:12 | a | 4294967295 | +| test.c:432:17:432:17 | a | 4294967295 | +| test.c:432:33:432:33 | b | 4294967295 | +| test.c:432:38:432:38 | b | 4294967295 | +| test.c:433:13:433:13 | a | 11 | +| test.c:433:15:433:15 | b | 23 | +| test.c:434:5:434:9 | total | 0 | +| test.c:434:14:434:14 | r | 253 | +| test.c:436:12:436:12 | a | 4294967295 | +| test.c:436:17:436:17 | a | 4294967295 | +| test.c:436:33:436:33 | b | 4294967295 | +| test.c:436:38:436:38 | b | 4294967295 | +| test.c:437:13:437:13 | a | 11 | +| test.c:437:15:437:15 | b | 23 | +| test.c:438:5:438:9 | total | 253 | +| test.c:438:14:438:14 | r | 253 | +| test.c:440:12:440:12 | a | 4294967295 | +| test.c:440:17:440:17 | a | 4294967295 | +| test.c:440:34:440:34 | b | 4294967295 | +| test.c:440:39:440:39 | b | 4294967295 | +| test.c:441:13:441:13 | a | 11 | +| test.c:441:15:441:15 | b | 23 | +| test.c:442:5:442:9 | total | 506 | +| test.c:442:14:442:14 | r | 253 | +| test.c:445:10:445:14 | total | 759 | +| test.c:451:12:451:12 | b | 4294967295 | +| test.c:451:17:451:17 | b | 4294967295 | +| test.c:452:16:452:16 | b | 23 | +| test.c:453:5:453:9 | total | 0 | +| test.c:453:14:453:14 | r | 253 | +| test.c:455:12:455:12 | b | 4294967295 | +| test.c:455:17:455:17 | b | 4294967295 | +| test.c:456:16:456:16 | b | 23 | +| test.c:457:5:457:9 | total | 253 | +| test.c:457:14:457:14 | r | 253 | +| test.c:459:13:459:13 | b | 4294967295 | +| test.c:459:18:459:18 | b | 4294967295 | +| test.c:460:16:460:16 | b | 23 | +| 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 | 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 | 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 | 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 | 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 | +| test.cpp:18:30:18:30 | x | 2147483647 | +| test.cpp:19:10:19:11 | x0 | 127 | +| test.cpp:27:7:27:7 | y | 2147483647 | +| test.cpp:28:5:28:5 | x | 2147483647 | +| test.cpp:30:7:30:7 | y | 2147483647 | +| test.cpp:31:5:31:5 | x | 2147483647 | +| test.cpp:33:7:33:7 | y | 2147483647 | +| test.cpp:34:5:34:5 | x | 2147483647 | +| test.cpp:36:7:36:7 | y | 2147483647 | +| test.cpp:37:5:37:5 | x | 2147483647 | +| test.cpp:39:7:39:7 | y | 2147483647 | +| test.cpp:40:5:40:5 | x | 2147483647 | +| test.cpp:42:7:42:7 | y | 2147483647 | +| test.cpp:43:5:43:5 | x | 2147483647 | +| test.cpp:45:7:45:7 | y | 2147483647 | +| test.cpp:46:5:46:5 | x | 2147483647 | +| test.cpp:51:7:51:7 | x | 2147483647 | +| test.cpp:52:21:52:21 | x | 0 | +| test.cpp:53:5:53:5 | t | 0 | +| test.cpp:53:15:53:16 | xb | 0 | +| test.cpp:56:7:56:7 | x | 2147483647 | +| test.cpp:57:21:57:21 | x | 2147483647 | +| test.cpp:58:5:58:5 | t | 0 | +| test.cpp:58:15:58:16 | xb | 1 | +| test.cpp:61:7:61:7 | x | 2147483647 | +| test.cpp:62:21:62:21 | x | -1 | +| test.cpp:63:5:63:5 | t | 1 | +| test.cpp:63:15:63:16 | xb | 1 | +| test.cpp:66:19:66:19 | x | 2147483647 | +| test.cpp:67:3:67:3 | t | 2 | +| test.cpp:67:13:67:14 | xb | 1 | +| test.cpp:69:10:69:10 | b | 1 | +| test.cpp:69:21:69:21 | t | 3 | +| test.cpp:74:30:74:30 | c | 255 | +| test.cpp:74:34:74:34 | c | 255 | +| test.cpp:75:22:75:30 | c_times_2 | 510 | +| test.cpp:77:5:77:13 | c_times_2 | 510 | +| test.cpp:79:3:79:11 | c_times_2 | 510 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.ql b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.ql index 341e5784aa3..26d188ce89c 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.ql @@ -1,4 +1,4 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis from VariableAccess expr -select expr, upperBound(expr) +select expr, upperBound(expr).toString() diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c index a2a67402a8e..9fc257e3eeb 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c @@ -385,10 +385,39 @@ void bitwise_ands() void unsigned_mult(unsigned int x, unsigned int y) { if(x < 13 && y < 35) { - if(x * y > 1024) {} // always false [NOT DETECTED] + if(x * y > 1024) {} // always false if(x * y < 204) {} if(x >= 3 && y >= 2) { - if(x * y < 5) {} // always false [NOT DETECTED] + if(x * y < 5) {} // always false } } -} \ No newline at end of file +} + +void mult_rounding() { + unsigned long x, y, xy; + x = y = 1000000003UL; // 1e9 + 3 + xy = 1000000006000000009UL; // x * y, precisely + // Even though the range analysis wrongly considers x*y to be xy - 9, there + // are no PointlessComparison false positives in these tests because alerts + // are suppressed when ulp() < 1, which roughly means that the number is + // larger than 2^53. + if (x * y < xy) {} // always false [NOT DETECTED] + if (x * y > xy) {} // always false [NOT DETECTED] +} + +void mult_overflow() { + unsigned long x, y; + // The following two numbers multiply to 2^64 + 1, which is 1 when truncated + // to 64-bit unsigned. + x = 274177UL; + y = 67280421310721UL; + if (x * y == 1) {} // always true [BUG: reported as always false] + + // This bug appears to be caused by + // `RangeAnalysisUtils::typeUpperBound(unsigned long)` having a result of + // 2**64 + 384, making the range analysis think that the multiplication can't + // overflow. The correct `typeUpperBound` would be 2**64 - 1, but we can't + // represent that with a QL float or int. We could make `typeUpperBound` + // exclusive instead of inclusive, but there is no exclusive upper bound for + // floats. +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected index c2c6cf6f14d..ca99f8e6b03 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected @@ -41,7 +41,10 @@ | PointlessComparison.c:372:6:372:16 | ... >= ... | Comparison is always true because ... >> ... >= 1. | | PointlessComparison.c:373:6:373:16 | ... >= ... | Comparison is always false because ... >> ... <= 1. | | PointlessComparison.c:383:6:383:17 | ... >= ... | Comparison is always false because ... & ... <= 2. | -| PointlessComparison.cpp:36:6:36:33 | ... >= ... | Comparison is always false because ... >> ... <= 9223372036854776000. | +| 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 ... * ... >= 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. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/IntegerOverflowTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/IntegerOverflowTainted.expected index d2b6499d40e..1d9a9d6ea66 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/IntegerOverflowTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/IntegerOverflowTainted.expected @@ -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 | diff --git a/csharp/.gitignore b/csharp/.gitignore index f81ecc73dff..0701c11fe1d 100644 --- a/csharp/.gitignore +++ b/csharp/.gitignore @@ -10,4 +10,5 @@ csharp.log **/bin/Release *.tlog .vs -*.user \ No newline at end of file +*.user +.vscode/launch.json \ No newline at end of file diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs index a4b1a4beb09..068cf2368fd 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs @@ -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); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 982d21b2569..aeb57609b8a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -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); }); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs index cb12918e72e..23aa8af9721 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs @@ -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 diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs index 4f239083d24..099080705c5 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs @@ -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(). FirstOrDefault(); } @@ -112,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Entities { get { - return symbol. + return BodyDeclaringSymbol. DeclaringSyntaxReferences. SelectMany(r => r.GetSyntax().ChildNodes()). OfType(). diff --git a/csharp/ql/src/printAst.ql b/csharp/ql/src/printAst.ql new file mode 100644 index 00000000000..b02193b257a --- /dev/null +++ b/csharp/ql/src/printAst.ql @@ -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()) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/Attribute.qll b/csharp/ql/src/semmle/code/csharp/Attribute.qll index fd19423441e..2818f4b001b 100644 --- a/csharp/ql/src/semmle/code/csharp/Attribute.qll +++ b/csharp/ql/src/semmle/code/csharp/Attribute.qll @@ -93,4 +93,6 @@ class Attribute extends TopLevelExprParent, @attribute { result = "[" + name + "(...)]" ) } + + override string getAPrimaryQlClass() { result = "Attribute" } } diff --git a/csharp/ql/src/semmle/code/csharp/Callable.qll b/csharp/ql/src/semmle/code/csharp/Callable.qll index 4e0ee381dbe..3d1eb96e806 100644 --- a/csharp/ql/src/semmle/code/csharp/Callable.qll +++ b/csharp/ql/src/semmle/code/csharp/Callable.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/Element.qll b/csharp/ql/src/semmle/code/csharp/Element.qll index 521138db1b5..f9ebbc5bef9 100644 --- a/csharp/ql/src/semmle/code/csharp/Element.qll +++ b/csharp/ql/src/semmle/code/csharp/Element.qll @@ -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 = "???" } } diff --git a/csharp/ql/src/semmle/code/csharp/Event.qll b/csharp/ql/src/semmle/code/csharp/Event.qll index 6b4ecc39190..a5b46c600fc 100644 --- a/csharp/ql/src/semmle/code/csharp/Event.qll +++ b/csharp/ql/src/semmle/code/csharp/Event.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/Generics.qll b/csharp/ql/src/semmle/code/csharp/Generics.qll index 9efdb46b867..656fb2ebd76 100644 --- a/csharp/ql/src/semmle/code/csharp/Generics.qll +++ b/csharp/ql/src/semmle/code/csharp/Generics.qll @@ -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" } } /** diff --git a/csharp/ql/src/semmle/code/csharp/Implements.qll b/csharp/ql/src/semmle/code/csharp/Implements.qll index 5ea4b51bfa2..7b535817039 100644 --- a/csharp/ql/src/semmle/code/csharp/Implements.qll +++ b/csharp/ql/src/semmle/code/csharp/Implements.qll @@ -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.B.C`. + * 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 + ) ) } diff --git a/csharp/ql/src/semmle/code/csharp/Namespace.qll b/csharp/ql/src/semmle/code/csharp/Namespace.qll index c686d61a5a5..ed1fece2ae6 100644 --- a/csharp/ql/src/semmle/code/csharp/Namespace.qll +++ b/csharp/ql/src/semmle/code/csharp/Namespace.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/PrintAst.ql b/csharp/ql/src/semmle/code/csharp/PrintAst.ql new file mode 100644 index 00000000000..3867fd2990f --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/PrintAst.ql @@ -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) } +} diff --git a/csharp/ql/src/semmle/code/csharp/PrintAst.qll b/csharp/ql/src/semmle/code/csharp/PrintAst.qll new file mode 100644 index 00000000000..36eca6699dc --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/PrintAst.qll @@ -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" +} diff --git a/csharp/ql/src/semmle/code/csharp/Property.qll b/csharp/ql/src/semmle/code/csharp/Property.qll index d71a1034226..224d7edb48c 100644 --- a/csharp/ql/src/semmle/code/csharp/Property.qll +++ b/csharp/ql/src/semmle/code/csharp/Property.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/Stmt.qll b/csharp/ql/src/semmle/code/csharp/Stmt.qll index d020e9afebf..a841489d825 100644 --- a/csharp/ql/src/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/src/semmle/code/csharp/Stmt.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index 41127586a89..a55dba2ac5f 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -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" } } /** diff --git a/csharp/ql/src/semmle/code/csharp/Unification.qll b/csharp/ql/src/semmle/code/csharp/Unification.qll index 2c7545c7609..4c057ad8c03 100644 --- a/csharp/ql/src/semmle/code/csharp/Unification.qll +++ b/csharp/ql/src/semmle/code/csharp/Unification.qll @@ -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.B.C`. + * 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 = diff --git a/csharp/ql/src/semmle/code/csharp/Using.qll b/csharp/ql/src/semmle/code/csharp/Using.qll index cc165873d41..9a9da8cc4fa 100644 --- a/csharp/ql/src/semmle/code/csharp/Using.qll +++ b/csharp/ql/src/semmle/code/csharp/Using.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/Variable.qll b/csharp/ql/src/semmle/code/csharp/Variable.qll index 183d08c1eaa..ed1c5c6fed8 100644 --- a/csharp/ql/src/semmle/code/csharp/Variable.qll +++ b/csharp/ql/src/semmle/code/csharp/Variable.qll @@ -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" } } /** diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 5042dce683f..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -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() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -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() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 5042dce683f..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -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() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 5042dce683f..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -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() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 5042dce683f..8c210edbe5f 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -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() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -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 + ")") } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 85cdb3522da..9813c0299ef 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -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 diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll index a935886f635..ab3ea182056 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/ArithmeticOperation.qll b/csharp/ql/src/semmle/code/csharp/exprs/ArithmeticOperation.qll index 38033b9a955..ac98c0eafcf 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/ArithmeticOperation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/ArithmeticOperation.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Assignment.qll b/csharp/ql/src/semmle/code/csharp/exprs/Assignment.qll index 9bfeffaeda2..88ef770160a 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Assignment.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Assignment.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/BitwiseOperation.qll b/csharp/ql/src/semmle/code/csharp/exprs/BitwiseOperation.qll index c96738b6961..0ae16bb5065 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/BitwiseOperation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/BitwiseOperation.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll index 7f17ef40297..90225a9aec3 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Call.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Call.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/ComparisonOperation.qll b/csharp/ql/src/semmle/code/csharp/exprs/ComparisonOperation.qll index 6ebb8e40ade..e48aabd76a7 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/ComparisonOperation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/ComparisonOperation.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll b/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll index 1d309b6e7c1..42bdcdf1a0d 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Creation.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Dynamic.qll b/csharp/ql/src/semmle/code/csharp/exprs/Dynamic.qll index f2cf6b71e79..ea6012ca3e1 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Dynamic.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Dynamic.qll @@ -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" } } /** diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll index cf95a524350..d410dd06561 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Expr.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Literal.qll b/csharp/ql/src/semmle/code/csharp/exprs/Literal.qll index 1a8231e7c18..0ca9f6d0db0 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Literal.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Literal.qll @@ -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" } +} diff --git a/csharp/ql/src/semmle/code/csharp/exprs/LogicalOperation.qll b/csharp/ql/src/semmle/code/csharp/exprs/LogicalOperation.qll index 81e7a5e42d5..e94d8ff93e7 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/LogicalOperation.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/LogicalOperation.qll @@ -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" } } diff --git a/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll b/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll index 21ca1431012..c84fa47a103 100644 --- a/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll +++ b/csharp/ql/src/semmle/code/csharp/frameworks/system/Xml.qll @@ -2,7 +2,7 @@ import csharp private import semmle.code.csharp.frameworks.System -private import semmle.code.csharp.dataflow.DataFlow2 +private import semmle.code.csharp.dataflow.DataFlow3 /** The `System.Xml` namespace. */ class SystemXmlNamespace extends Namespace { @@ -163,7 +163,7 @@ class XmlReaderSettingsCreation extends ObjectCreation { } } -private class SettingsDataFlowConfig extends DataFlow2::Configuration { +private class SettingsDataFlowConfig extends DataFlow3::Configuration { SettingsDataFlowConfig() { this = "SettingsDataFlowConfig" } override predicate isSource(DataFlow::Node source) { diff --git a/csharp/ql/test/experimental/ir/ir/PrintAst.expected b/csharp/ql/test/experimental/ir/ir/PrintAst.expected new file mode 100644 index 00000000000..fddb231db2a --- /dev/null +++ b/csharp/ql/test/experimental/ir/ir/PrintAst.expected @@ -0,0 +1,1150 @@ +array.cs: +# 1| [Class] ArrayTest +# 2| 5: [Method] one_dim_init_acc +# 3| 4: [BlockStmt] {...} +# 4| 0: [LocalVariableDeclStmt] ... ...; +# 4| 0: [LocalVariableDeclAndInitExpr] Int32[] one_dim = ... +# 4| 0: [ArrayCreation] array creation of type Int32[] +# 4| -1: [ArrayInitializer] { ..., ... } +# 4| 0: [IntLiteral] 100 +# 4| 1: [IntLiteral] 101 +# 4| 2: [IntLiteral] 102 +# 4| 1: [LocalVariableAccess] access to local variable one_dim +# 5| 1: [ExprStmt] ...; +# 5| 0: [AssignExpr] ... = ... +# 5| 0: [IntLiteral] 1000 +# 5| 1: [ArrayAccess] access to array element +# 5| -1: [LocalVariableAccess] access to local variable one_dim +# 5| 0: [IntLiteral] 0 +# 6| 2: [ExprStmt] ...; +# 6| 0: [AssignExpr] ... = ... +# 6| 0: [ArrayAccess] access to array element +# 6| -1: [LocalVariableAccess] access to local variable one_dim +# 6| 0: [IntLiteral] 0 +# 6| 1: [ArrayAccess] access to array element +# 6| -1: [LocalVariableAccess] access to local variable one_dim +# 6| 0: [IntLiteral] 1 +# 7| 3: [ExprStmt] ...; +# 7| 0: [AssignExpr] ... = ... +# 7| 0: [IntLiteral] 1003 +# 7| 1: [ArrayAccess] access to array element +# 7| -1: [LocalVariableAccess] access to local variable one_dim +# 7| 0: [IntLiteral] 1 +# 9| 4: [LocalVariableDeclStmt] ... ...; +# 9| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 9| 0: [IntLiteral] 0 +# 9| 1: [LocalVariableAccess] access to local variable i +# 10| 5: [ExprStmt] ...; +# 10| 0: [AssignExpr] ... = ... +# 10| 0: [IntLiteral] 0 +# 10| 1: [ArrayAccess] access to array element +# 10| -1: [LocalVariableAccess] access to local variable one_dim +# 10| 0: [LocalVariableAccess] access to local variable i +# 13| 6: [Method] twod_and_init_acc +# 14| 4: [BlockStmt] {...} +# 15| 0: [LocalVariableDeclStmt] ... ...; +# 15| 0: [LocalVariableDeclAndInitExpr] Int32[,] a = ... +# 15| 0: [ArrayCreation] array creation of type Int32[,] +# 15| -1: [ArrayInitializer] { ..., ... } +# 15| 0: [ArrayInitializer] { ..., ... } +# 15| 0: [IntLiteral] 100 +# 15| 1: [IntLiteral] 101 +# 15| 1: [ArrayInitializer] { ..., ... } +# 15| 0: [IntLiteral] 102 +# 15| 1: [IntLiteral] 103 +# 15| 1: [LocalVariableAccess] access to local variable a +# 16| 1: [LocalVariableDeclStmt] ... ...; +# 16| 0: [LocalVariableDeclAndInitExpr] Int32[,] b = ... +# 16| 0: [ArrayCreation] array creation of type Int32[,] +# 16| 0: [IntLiteral] 5 +# 16| 1: [IntLiteral] 5 +# 16| 1: [LocalVariableAccess] access to local variable b +# 17| 2: [LocalVariableDeclStmt] ... ...; +# 17| 0: [LocalVariableDeclAndInitExpr] Int32[,] c = ... +# 17| 0: [ArrayCreation] array creation of type Int32[,] +# 17| -1: [ArrayInitializer] { ..., ... } +# 17| 0: [ArrayInitializer] { ..., ... } +# 17| 0: [IntLiteral] 100 +# 17| 1: [IntLiteral] 101 +# 17| 1: [ArrayInitializer] { ..., ... } +# 17| 0: [IntLiteral] 102 +# 17| 1: [IntLiteral] 103 +# 17| 0: [IntLiteral] 2 +# 17| 1: [IntLiteral] 2 +# 17| 1: [LocalVariableAccess] access to local variable c +# 18| 3: [LocalVariableDeclStmt] ... ...; +# 18| 0: [LocalVariableDeclAndInitExpr] Int32[,] d = ... +# 18| 0: [ArrayCreation] array creation of type Int32[,] +# 18| -1: [ArrayInitializer] { ..., ... } +# 18| 0: [ArrayInitializer] { ..., ... } +# 18| 0: [IntLiteral] 100 +# 18| 1: [IntLiteral] 101 +# 18| 1: [ArrayInitializer] { ..., ... } +# 18| 0: [IntLiteral] 102 +# 18| 1: [IntLiteral] 103 +# 18| 1: [LocalVariableAccess] access to local variable d +# 19| 4: [LocalVariableDeclStmt] ... ...; +# 19| 0: [LocalVariableDeclAndInitExpr] Int32[,] e = ... +# 19| 0: [LocalVariableAccess] access to local variable a +# 19| 1: [LocalVariableAccess] access to local variable e +# 20| 5: [ExprStmt] ...; +# 20| 0: [AssignExpr] ... = ... +# 20| 0: [UnaryMinusExpr] -... +# 20| 0: [IntLiteral] 1 +# 20| 1: [ArrayAccess] access to array element +# 20| -1: [LocalVariableAccess] access to local variable e +# 20| 0: [IntLiteral] 1 +# 20| 1: [IntLiteral] 1 +assignop.cs: +# 3| [Class] AssignOp +# 4| 5: [Method] Main +# 4| 4: [BlockStmt] {...} +# 5| 0: [LocalVariableDeclStmt] ... ...; +# 5| 0: [LocalVariableDeclAndInitExpr] Int32 a = ... +# 5| 0: [IntLiteral] 1 +# 5| 1: [LocalVariableAccess] access to local variable a +# 6| 1: [LocalVariableDeclStmt] ... ...; +# 6| 0: [LocalVariableDeclAndInitExpr] Int32 c = ... +# 6| 0: [IntLiteral] 1 +# 6| 1: [LocalVariableAccess] access to local variable c +# 8| 2: [ExprStmt] ...; +# 8| 0: [AssignAddExpr] ... += ... +# 8| 0: [LocalVariableAccess] access to local variable a +# 8| 1: [LocalVariableAccess] access to local variable c +# 9| 3: [ExprStmt] ...; +# 9| 0: [AssignSubExpr] ... -= ... +# 9| 0: [LocalVariableAccess] access to local variable a +# 9| 1: [LocalVariableAccess] access to local variable c +# 10| 4: [ExprStmt] ...; +# 10| 0: [AssignMulExpr] ... *= ... +# 10| 0: [LocalVariableAccess] access to local variable a +# 10| 1: [LocalVariableAccess] access to local variable c +# 11| 5: [ExprStmt] ...; +# 11| 0: [AssignDivExpr] ... /= ... +# 11| 0: [LocalVariableAccess] access to local variable a +# 11| 1: [LocalVariableAccess] access to local variable c +# 12| 6: [ExprStmt] ...; +# 12| 0: [AssignRemExpr] ... %= ... +# 12| 0: [LocalVariableAccess] access to local variable a +# 12| 1: [LocalVariableAccess] access to local variable c +# 13| 7: [ExprStmt] ...; +# 13| 0: [AssignLShiftExpr] ... <<= ... +# 13| 0: [IntLiteral] 2 +# 13| 1: [LocalVariableAccess] access to local variable c +# 14| 8: [ExprStmt] ...; +# 14| 0: [AssignRShiftExpr] ... >>= ... +# 14| 0: [IntLiteral] 2 +# 14| 1: [LocalVariableAccess] access to local variable c +# 15| 9: [ExprStmt] ...; +# 15| 0: [AssignAndExpr] ... &= ... +# 15| 0: [IntLiteral] 2 +# 15| 1: [LocalVariableAccess] access to local variable c +# 16| 10: [ExprStmt] ...; +# 16| 0: [AssignXorExpr] ... ^= ... +# 16| 0: [IntLiteral] 2 +# 16| 1: [LocalVariableAccess] access to local variable c +# 17| 11: [ExprStmt] ...; +# 17| 0: [AssignOrExpr] ... |= ... +# 17| 0: [IntLiteral] 2 +# 17| 1: [LocalVariableAccess] access to local variable c +casts.cs: +# 9| [Class] Casts +# 11| 5: [Method] Main +# 12| 4: [BlockStmt] {...} +# 13| 0: [LocalVariableDeclStmt] ... ...; +# 13| 0: [LocalVariableDeclAndInitExpr] Casts_A Aobj = ... +# 13| 0: [ObjectCreation] object creation of type Casts_A +# 13| 1: [LocalVariableAccess] access to local variable Aobj +# 14| 1: [LocalVariableDeclStmt] ... ...; +# 14| 0: [LocalVariableDeclAndInitExpr] Casts_B bobjCE = ... +# 14| 0: [CastExpr] (...) ... +# 14| 0: [LocalVariableAccess] access to local variable Aobj +# 14| 1: [TypeAccess] access to type Casts_B +# 14| 1: [LocalVariableAccess] access to local variable bobjCE +# 15| 2: [LocalVariableDeclStmt] ... ...; +# 15| 0: [LocalVariableDeclAndInitExpr] Casts_B bobjAS = ... +# 15| 0: [AsExpr] ... as ... +# 15| 0: [LocalVariableAccess] access to local variable Aobj +# 15| 1: [TypeAccess] access to type Casts_B +# 15| 1: [LocalVariableAccess] access to local variable bobjAS +# 1| [Class] Casts_A +# 5| [Class] Casts_B +#-----| 3: (Base types) +# 5| 0: [Class] Casts_A +collections.cs: +# 3| [Class] Collections +# 5| 5: [Class] MyClass +# 7| 5: [Field] a +# 8| 6: [Field] b +# 11| 6: [Method] Main +# 12| 4: [BlockStmt] {...} +# 13| 0: [LocalVariableDeclStmt] ... ...; +# 13| 0: [LocalVariableDeclAndInitExpr] Dictionary dict = ... +# 13| 0: [ObjectCreation] object creation of type Dictionary +# 14| -1: [CollectionInitializer] { ..., ... } +# 15| 0: [ElementInitializer] call to method Add +# 15| 0: [IntLiteral] 0 +# 15| 1: [ObjectCreation] object creation of type MyClass +# 15| -1: [ObjectInitializer] { ..., ... } +# 15| 0: [MemberInitializer] ... = ... +# 15| 0: [StringLiteral] "Hello" +# 15| 1: [FieldAccess] access to field a +# 15| 1: [MemberInitializer] ... = ... +# 15| 0: [StringLiteral] "World" +# 15| 1: [FieldAccess] access to field b +# 16| 1: [ElementInitializer] call to method Add +# 16| 0: [IntLiteral] 1 +# 16| 1: [ObjectCreation] object creation of type MyClass +# 16| -1: [ObjectInitializer] { ..., ... } +# 16| 0: [MemberInitializer] ... = ... +# 16| 0: [StringLiteral] "Foo" +# 16| 1: [FieldAccess] access to field a +# 16| 1: [MemberInitializer] ... = ... +# 16| 0: [StringLiteral] "Bar" +# 16| 1: [FieldAccess] access to field b +# 13| 1: [LocalVariableAccess] access to local variable dict +constructor_init.cs: +# 1| [Class] BaseClass +# 3| 4: [Field] num +# 5| 5: [InstanceConstructor] BaseClass +# 6| 4: [BlockStmt] {...} +# 9| 6: [InstanceConstructor] BaseClass +#-----| 2: (Parameters) +# 9| 0: [Parameter] i +# 10| 4: [BlockStmt] {...} +# 11| 0: [ExprStmt] ...; +# 11| 0: [AssignExpr] ... = ... +# 11| 0: [ParameterAccess] access to parameter i +# 11| 1: [FieldAccess] access to field num +# 15| [Class] DerivedClass +#-----| 3: (Base types) +# 15| 0: [Class] BaseClass +# 17| 4: [InstanceConstructor] DerivedClass +# 17| 3: [ConstructorInitializer] call to constructor BaseClass +# 18| 4: [BlockStmt] {...} +# 21| 5: [InstanceConstructor] DerivedClass +#-----| 2: (Parameters) +# 21| 0: [Parameter] i +# 21| 3: [ConstructorInitializer] call to constructor BaseClass +# 21| 0: [ParameterAccess] access to parameter i +# 22| 4: [BlockStmt] {...} +# 25| 6: [InstanceConstructor] DerivedClass +#-----| 2: (Parameters) +# 25| 0: [Parameter] i +# 25| 1: [Parameter] j +# 25| 3: [ConstructorInitializer] call to constructor DerivedClass +# 25| 0: [ParameterAccess] access to parameter i +# 26| 4: [BlockStmt] {...} +# 29| 7: [Method] Main +# 30| 4: [BlockStmt] {...} +# 31| 0: [LocalVariableDeclStmt] ... ...; +# 31| 0: [LocalVariableDeclAndInitExpr] DerivedClass obj1 = ... +# 31| 0: [ObjectCreation] object creation of type DerivedClass +# 31| 1: [LocalVariableAccess] access to local variable obj1 +# 32| 1: [LocalVariableDeclStmt] ... ...; +# 32| 0: [LocalVariableDeclAndInitExpr] DerivedClass obj2 = ... +# 32| 0: [ObjectCreation] object creation of type DerivedClass +# 32| 0: [IntLiteral] 1 +# 32| 1: [LocalVariableAccess] access to local variable obj2 +# 33| 2: [LocalVariableDeclStmt] ... ...; +# 33| 0: [LocalVariableDeclAndInitExpr] DerivedClass obj3 = ... +# 33| 0: [ObjectCreation] object creation of type DerivedClass +# 33| 0: [IntLiteral] 1 +# 33| 1: [IntLiteral] 2 +# 33| 1: [LocalVariableAccess] access to local variable obj3 +crement.cs: +# 1| [Class] CrementOpsTest +# 3| 5: [Method] Main +# 4| 4: [BlockStmt] {...} +# 5| 0: [LocalVariableDeclStmt] ... ...; +# 5| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 5| 0: [IntLiteral] 10 +# 5| 1: [LocalVariableAccess] access to local variable x +# 6| 1: [LocalVariableDeclStmt] ... ...; +# 6| 0: [LocalVariableDeclAndInitExpr] Int32 a = ... +# 6| 0: [PostIncrExpr] ...++ +# 6| 0: [LocalVariableAccess] access to local variable x +# 6| 1: [LocalVariableAccess] access to local variable a +# 7| 2: [LocalVariableDeclStmt] ... ...; +# 7| 0: [LocalVariableDeclAndInitExpr] Int32 b = ... +# 7| 0: [PreDecrExpr] --... +# 7| 0: [LocalVariableAccess] access to local variable x +# 7| 1: [LocalVariableAccess] access to local variable b +# 8| 3: [LocalVariableDeclStmt] ... ...; +# 8| 0: [LocalVariableDeclAndInitExpr] Int32 c = ... +# 8| 0: [PreIncrExpr] ++... +# 8| 0: [LocalVariableAccess] access to local variable x +# 8| 1: [LocalVariableAccess] access to local variable c +# 9| 4: [ExprStmt] ...; +# 9| 0: [AssignExpr] ... = ... +# 9| 0: [PostDecrExpr] ...-- +# 9| 0: [LocalVariableAccess] access to local variable x +# 9| 1: [LocalVariableAccess] access to local variable x +delegates.cs: +# 3| [Class] Delegates +# 4| 5: [DelegateType] Del +#-----| 2: (Parameters) +# 4| 0: [Parameter] num +# 6| 6: [Method] returns +#-----| 2: (Parameters) +# 6| 0: [Parameter] ret +# 7| 4: [BlockStmt] {...} +# 8| 0: [ReturnStmt] return ...; +# 8| 0: [ParameterAccess] access to parameter ret +# 11| 7: [Method] Main +# 11| 4: [BlockStmt] {...} +# 12| 0: [LocalVariableDeclStmt] ... ...; +# 12| 0: [LocalVariableDeclAndInitExpr] Del del1 = ... +# 12| 0: [ExplicitDelegateCreation] delegate creation of type Del +# 12| 0: [MethodAccess] access to method returns +# 12| 1: [LocalVariableAccess] access to local variable del1 +# 13| 1: [ExprStmt] ...; +# 13| 0: [DelegateCall] delegate call +# 13| -1: [LocalVariableAccess] access to local variable del1 +# 13| 0: [IntLiteral] 5 +events.cs: +# 1| [Class] Events +# 3| 4: [DelegateType] MyDel +#-----| 2: (Parameters) +# 3| 0: [Parameter] str +# 4| 5: [Field] Inst +# 6| 6: [Event] MyEvent +# 6| 3: [AddEventAccessor] add_MyEvent +#-----| 2: (Parameters) +# 6| 0: [Parameter] value +# 6| 3: [RemoveEventAccessor] remove_MyEvent +#-----| 2: (Parameters) +# 6| 0: [Parameter] value +# 8| 7: [InstanceConstructor] Events +# 9| 4: [BlockStmt] {...} +# 10| 0: [ExprStmt] ...; +# 10| 0: [AssignExpr] ... = ... +# 10| 0: [ExplicitDelegateCreation] delegate creation of type MyDel +# 10| 0: [MethodAccess] access to method Fun +# 10| -1: [ThisAccess] this access +# 10| 1: [FieldAccess] access to field Inst +# 10| -1: [ThisAccess] this access +# 13| 8: [Method] AddEvent +# 14| 4: [BlockStmt] {...} +# 15| 0: [ExprStmt] ...; +# 15| 0: [AddEventExpr] ... += ... +# 15| 0: [FieldAccess] access to field Inst +# 15| -1: [ThisAccess] this access +# 15| 1: [EventAccess,EventCall] access to event MyEvent +# 15| -1: [ThisAccess] this access +# 18| 9: [Method] RemoveEvent +# 19| 4: [BlockStmt] {...} +# 20| 0: [ExprStmt] ...; +# 20| 0: [RemoveEventExpr] ... -= ... +# 20| 0: [FieldAccess] access to field Inst +# 20| -1: [ThisAccess] this access +# 20| 1: [EventAccess,EventCall] access to event MyEvent +# 20| -1: [ThisAccess] this access +# 23| 10: [Method] Fun +#-----| 2: (Parameters) +# 23| 0: [Parameter] str +# 24| 4: [BlockStmt] {...} +# 25| 0: [ReturnStmt] return ...; +# 25| 0: [ParameterAccess] access to parameter str +# 28| 11: [Method] Main +#-----| 2: (Parameters) +# 28| 0: [Parameter] args +# 29| 4: [BlockStmt] {...} +# 30| 0: [LocalVariableDeclStmt] ... ...; +# 30| 0: [LocalVariableDeclAndInitExpr] Events obj = ... +# 30| 0: [ObjectCreation] object creation of type Events +# 30| 1: [LocalVariableAccess] access to local variable obj +# 31| 1: [ExprStmt] ...; +# 31| 0: [MethodCall] call to method AddEvent +# 31| -1: [LocalVariableAccess] access to local variable obj +# 32| 2: [LocalVariableDeclStmt] ... ...; +# 32| 0: [LocalVariableDeclAndInitExpr] String result = ... +# 32| 0: [DelegateCall] delegate call +# 32| -1: [LocalVariableAccess] access to local variable obj +# 32| 0: [StringLiteral] "string" +# 32| 1: [LocalVariableAccess] access to local variable result +# 33| 3: [ExprStmt] ...; +# 33| 0: [MethodCall] call to method RemoveEvent +# 33| -1: [LocalVariableAccess] access to local variable obj +foreach.cs: +# 3| [Class] ForEach +# 4| 5: [Method] Main +# 4| 4: [BlockStmt] {...} +# 5| 0: [LocalVariableDeclStmt] ... ...; +# 5| 0: [LocalVariableDeclAndInitExpr] Int32[] a_array = ... +# 5| 0: [ArrayCreation] array creation of type Int32[] +# 5| -1: [ArrayInitializer] { ..., ... } +# 5| 0: [IntLiteral] 1 +# 5| 1: [IntLiteral] 2 +# 5| 2: [IntLiteral] 3 +# 5| 3: [IntLiteral] 4 +# 5| 4: [IntLiteral] 5 +# 5| 5: [IntLiteral] 6 +# 5| 6: [IntLiteral] 7 +# 5| 1: [LocalVariableAccess] access to local variable a_array +# 7| 1: [ForeachStmt] foreach (... ... in ...) ... +# 7| 0: [LocalVariableDeclExpr] Int32 items +# 7| 1: [LocalVariableAccess] access to local variable a_array +# 8| 2: [BlockStmt] {...} +# 9| 0: [LocalVariableDeclStmt] ... ...; +# 9| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 9| 0: [LocalVariableAccess] access to local variable items +# 9| 1: [LocalVariableAccess] access to local variable x +func_with_param_call.cs: +# 3| [Class] test_call_with_param +# 5| 5: [Method] f +#-----| 2: (Parameters) +# 5| 0: [Parameter] x +# 5| 1: [Parameter] y +# 6| 4: [BlockStmt] {...} +# 7| 0: [ReturnStmt] return ...; +# 7| 0: [AddExpr] ... + ... +# 7| 0: [ParameterAccess] access to parameter x +# 7| 1: [ParameterAccess] access to parameter y +# 10| 6: [Method] g +# 11| 4: [BlockStmt] {...} +# 12| 0: [ReturnStmt] return ...; +# 12| 0: [MethodCall] call to method f +# 12| 0: [IntLiteral] 2 +# 12| 1: [IntLiteral] 3 +indexers.cs: +# 1| [Class] Indexers +# 3| 5: [Class] MyClass +# 5| 5: [Field] address +# 5| 1: [AssignExpr] ... = ... +# 5| 0: [ArrayCreation] array creation of type String[] +# 5| 0: [IntLiteral] 2 +# 5| 1: [FieldAccess] access to field address +# 6| 6: [Indexer] Item +#-----| 1: (Parameters) +# 6| 0: [Parameter] index +# 8| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 6| 0: [Parameter] index +# 9| 4: [BlockStmt] {...} +# 10| 0: [ReturnStmt] return ...; +# 10| 0: [ArrayAccess] access to array element +# 10| -1: [FieldAccess] access to field address +# 10| 0: [ParameterAccess] access to parameter index +# 12| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 6| 0: [Parameter] index +# 12| 1: [Parameter] value +# 13| 4: [BlockStmt] {...} +# 14| 0: [ExprStmt] ...; +# 14| 0: [AssignExpr] ... = ... +# 14| 0: [ParameterAccess] access to parameter value +# 14| 1: [ArrayAccess] access to array element +# 14| -1: [FieldAccess] access to field address +# 14| 0: [ParameterAccess] access to parameter index +# 19| 6: [Method] Main +# 20| 4: [BlockStmt] {...} +# 21| 0: [LocalVariableDeclStmt] ... ...; +# 21| 0: [LocalVariableDeclAndInitExpr] MyClass inst = ... +# 21| 0: [ObjectCreation] object creation of type MyClass +# 21| 1: [LocalVariableAccess] access to local variable inst +# 22| 1: [ExprStmt] ...; +# 22| 0: [AssignExpr] ... = ... +# 22| 0: [StringLiteral] "str1" +# 22| 1: [IndexerCall] access to indexer +# 22| -1: [LocalVariableAccess] access to local variable inst +# 22| 0: [IntLiteral] 0 +# 23| 2: [ExprStmt] ...; +# 23| 0: [AssignExpr] ... = ... +# 23| 0: [StringLiteral] "str1" +# 23| 1: [IndexerCall] access to indexer +# 23| -1: [LocalVariableAccess] access to local variable inst +# 23| 0: [IntLiteral] 1 +# 24| 3: [ExprStmt] ...; +# 24| 0: [AssignExpr] ... = ... +# 24| 0: [IndexerCall] access to indexer +# 24| -1: [LocalVariableAccess] access to local variable inst +# 24| 0: [IntLiteral] 0 +# 24| 1: [IndexerCall] access to indexer +# 24| -1: [LocalVariableAccess] access to local variable inst +# 24| 0: [IntLiteral] 1 +inheritance_polymorphism.cs: +# 1| [Class] A +# 3| 5: [Method] function +# 4| 4: [BlockStmt] {...} +# 5| 0: [ReturnStmt] return ...; +# 5| 0: [IntLiteral] 0 +# 13| [Class] C +#-----| 3: (Base types) +# 13| 0: [Class] B +# 15| 5: [Method] function +# 16| 4: [BlockStmt] {...} +# 17| 0: [ReturnStmt] return ...; +# 17| 0: [IntLiteral] 1 +# 21| [Class] Program +# 23| 5: [Method] Main +# 24| 4: [BlockStmt] {...} +# 25| 0: [LocalVariableDeclStmt] ... ...; +# 25| 0: [LocalVariableDeclAndInitExpr] B objB = ... +# 25| 0: [ObjectCreation] object creation of type B +# 25| 1: [LocalVariableAccess] access to local variable objB +# 26| 1: [ExprStmt] ...; +# 26| 0: [MethodCall] call to method function +# 26| -1: [LocalVariableAccess] access to local variable objB +# 29| 2: [LocalVariableDeclStmt] ... ...; +# 29| 0: [LocalVariableDeclExpr] A objA +# 30| 3: [ExprStmt] ...; +# 30| 0: [AssignExpr] ... = ... +# 30| 0: [LocalVariableAccess] access to local variable objB +# 30| 1: [LocalVariableAccess] access to local variable objA +# 31| 4: [ExprStmt] ...; +# 31| 0: [MethodCall] call to method function +# 31| -1: [LocalVariableAccess] access to local variable objA +# 33| 5: [LocalVariableDeclStmt] ... ...; +# 33| 0: [LocalVariableDeclAndInitExpr] A objC = ... +# 33| 0: [ObjectCreation] object creation of type C +# 33| 1: [LocalVariableAccess] access to local variable objC +# 34| 6: [ExprStmt] ...; +# 34| 0: [MethodCall] call to method function +# 34| -1: [LocalVariableAccess] access to local variable objC +# 9| [Class] B +#-----| 3: (Base types) +# 9| 0: [Class] A +inoutref.cs: +# 1| [Class] MyClass +# 2| 5: [Field] fld +# 5| [Struct] MyStruct +# 6| 5: [Field] fld +# 9| [Class] InOutRef +# 11| 5: [Method] set +#-----| 2: (Parameters) +# 11| 0: [Parameter] o1 +# 11| 1: [Parameter] o2 +# 12| 4: [BlockStmt] {...} +# 13| 0: [ExprStmt] ...; +# 13| 0: [AssignExpr] ... = ... +# 13| 0: [ParameterAccess] access to parameter o2 +# 13| 1: [ParameterAccess] access to parameter o1 +# 16| 6: [Method] F +#-----| 2: (Parameters) +# 16| 0: [Parameter] a +# 16| 1: [Parameter] b +# 16| 2: [Parameter] b1 +# 16| 3: [Parameter] c +# 16| 4: [Parameter] c1 +# 17| 4: [BlockStmt] {...} +# 18| 0: [ExprStmt] ...; +# 18| 0: [AssignExpr] ... = ... +# 18| 0: [IntLiteral] 0 +# 18| 1: [FieldAccess] access to field fld +# 18| -1: [ParameterAccess] access to parameter b +# 19| 1: [ExprStmt] ...; +# 19| 0: [AssignExpr] ... = ... +# 19| 0: [FieldAccess] access to field fld +# 19| -1: [ParameterAccess] access to parameter b +# 19| 1: [ParameterAccess] access to parameter a +# 21| 2: [ExprStmt] ...; +# 21| 0: [AssignExpr] ... = ... +# 21| 0: [IntLiteral] 10 +# 21| 1: [FieldAccess] access to field fld +# 21| -1: [ParameterAccess] access to parameter c +# 22| 3: [ExprStmt] ...; +# 22| 0: [AssignExpr] ... = ... +# 22| 0: [FieldAccess] access to field fld +# 22| -1: [ParameterAccess] access to parameter c +# 22| 1: [ParameterAccess] access to parameter a +# 24| 4: [ExprStmt] ...; +# 24| 0: [AssignExpr] ... = ... +# 24| 0: [ParameterAccess] access to parameter b1 +# 24| 1: [ParameterAccess] access to parameter b +# 26| 5: [ExprStmt] ...; +# 26| 0: [MethodCall] call to method set +# 26| 0: [ParameterAccess] access to parameter c +# 26| 1: [ParameterAccess] access to parameter c1 +# 29| 7: [Method] Main +# 30| 4: [BlockStmt] {...} +# 31| 0: [LocalVariableDeclStmt] ... ...; +# 31| 0: [LocalVariableDeclAndInitExpr] Int32 a = ... +# 31| 0: [IntLiteral] 0 +# 31| 1: [LocalVariableAccess] access to local variable a +# 32| 1: [LocalVariableDeclStmt] ... ...; +# 32| 0: [LocalVariableDeclAndInitExpr] MyStruct b = ... +# 32| 0: [ObjectCreation] object creation of type MyStruct +# 32| 1: [LocalVariableAccess] access to local variable b +# 33| 2: [LocalVariableDeclStmt] ... ...; +# 33| 0: [LocalVariableDeclAndInitExpr] MyClass c = ... +# 33| 0: [ObjectCreation] object creation of type MyClass +# 33| 1: [LocalVariableAccess] access to local variable c +# 34| 3: [ExprStmt] ...; +# 34| 0: [MethodCall] call to method F +# 34| 0: [LocalVariableAccess] access to local variable a +# 34| 1: [LocalVariableAccess] access to local variable b +# 34| 2: [LocalVariableAccess] access to local variable b +# 34| 3: [LocalVariableAccess] access to local variable c +# 34| 4: [LocalVariableAccess] access to local variable c +# 36| 4: [LocalVariableDeclStmt] ... ...; +# 36| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 36| 0: [FieldAccess] access to field fld +# 36| -1: [LocalVariableAccess] access to local variable b +# 36| 1: [LocalVariableAccess] access to local variable x +isexpr.cs: +# 1| [Class] Is_A +# 3| 5: [Field] x +# 6| [Class] IsExpr +# 8| 5: [Method] Main +# 9| 4: [BlockStmt] {...} +# 10| 0: [LocalVariableDeclStmt] ... ...; +# 10| 0: [LocalVariableDeclAndInitExpr] Is_A obj = ... +# 10| 0: [NullLiteral] null +# 10| 1: [LocalVariableAccess] access to local variable obj +# 12| 1: [LocalVariableDeclStmt] ... ...; +# 12| 0: [LocalVariableDeclAndInitExpr] Object o = ... +# 12| 0: [LocalVariableAccess] access to local variable obj +# 12| 1: [LocalVariableAccess] access to local variable o +# 13| 2: [IfStmt] if (...) ... +# 13| 0: [IsExpr] ... is ... +# 13| 0: [LocalVariableAccess] access to local variable o +# 13| 1: [VariablePatternExpr] Is_A tmp +# 14| 1: [BlockStmt] {...} +# 15| 0: [LocalVariableDeclStmt] ... ...; +# 15| 0: [LocalVariableDeclAndInitExpr] Int32 res = ... +# 15| 0: [FieldAccess] access to field x +# 15| -1: [LocalVariableAccess] access to local variable tmp +# 15| 1: [LocalVariableAccess] access to local variable res +# 17| 3: [IfStmt] if (...) ... +# 17| 0: [IsExpr] ... is ... +# 17| 0: [LocalVariableAccess] access to local variable o +# 17| 1: [TypeAccessPatternExpr] access to type Is_A +# 18| 1: [BlockStmt] {...} +jumps.cs: +# 3| [Class] Jumps +# 5| 5: [Method] Main +# 6| 4: [BlockStmt] {...} +# 7| 0: [ForStmt] for (...;...;...) ... +# 7| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 7| 0: [IntLiteral] 1 +# 7| 1: [LocalVariableAccess] access to local variable i +# 7| 0: [LEExpr] ... <= ... +# 7| 0: [LocalVariableAccess] access to local variable i +# 7| 1: [IntLiteral] 10 +# 7| 1: [PostIncrExpr] ...++ +# 7| 0: [LocalVariableAccess] access to local variable i +# 8| 2: [BlockStmt] {...} +# 9| 0: [IfStmt] if (...) ... +# 9| 0: [EQExpr] ... == ... +# 9| 0: [LocalVariableAccess] access to local variable i +# 9| 1: [IntLiteral] 3 +# 10| 1: [ContinueStmt] continue; +# 11| 2: [IfStmt] if (...) ... +# 11| 0: [EQExpr] ... == ... +# 11| 0: [LocalVariableAccess] access to local variable i +# 11| 1: [IntLiteral] 5 +# 12| 1: [BreakStmt] break; +# 13| 1: [ExprStmt] ...; +# 13| 0: [MethodCall] call to method WriteLine +# 13| -1: [TypeAccess] access to type Console +# 13| 0: [StringLiteral] "BreakAndContinue" +# 16| 1: [ForStmt] for (...;...;...) ... +# 16| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 16| 0: [IntLiteral] 0 +# 16| 1: [LocalVariableAccess] access to local variable i +# 16| 0: [LTExpr] ... < ... +# 16| 0: [LocalVariableAccess] access to local variable i +# 16| 1: [IntLiteral] 10 +# 17| 1: [BlockStmt] {...} +# 18| 0: [ExprStmt] ...; +# 18| 0: [PostIncrExpr] ...++ +# 18| 0: [LocalVariableAccess] access to local variable i +# 19| 1: [ContinueStmt] continue; +# 22| 2: [LocalVariableDeclStmt] ... ...; +# 22| 0: [LocalVariableDeclAndInitExpr] Int32 a = ... +# 22| 0: [IntLiteral] 0 +# 22| 1: [LocalVariableAccess] access to local variable a +# 23| 3: [WhileStmt] while (...) ... +# 23| 0: [BoolLiteral] true +# 24| 1: [BlockStmt] {...} +# 25| 0: [ExprStmt] ...; +# 25| 0: [PostIncrExpr] ...++ +# 25| 0: [LocalVariableAccess] access to local variable a +# 26| 1: [IfStmt] if (...) ... +# 26| 0: [EQExpr] ... == ... +# 26| 0: [LocalVariableAccess] access to local variable a +# 26| 1: [IntLiteral] 5 +# 27| 1: [ContinueStmt] continue; +# 28| 2: [IfStmt] if (...) ... +# 28| 0: [EQExpr] ... == ... +# 28| 0: [LocalVariableAccess] access to local variable a +# 28| 1: [IntLiteral] 10 +# 29| 1: [BreakStmt] break; +# 32| 4: [ForStmt] for (...;...;...) ... +# 32| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 32| 0: [IntLiteral] 1 +# 32| 1: [LocalVariableAccess] access to local variable i +# 32| 0: [LEExpr] ... <= ... +# 32| 0: [LocalVariableAccess] access to local variable i +# 32| 1: [IntLiteral] 10 +# 32| 1: [PostIncrExpr] ...++ +# 32| 0: [LocalVariableAccess] access to local variable i +# 33| 2: [BlockStmt] {...} +# 34| 0: [IfStmt] if (...) ... +# 34| 0: [EQExpr] ... == ... +# 34| 0: [LocalVariableAccess] access to local variable i +# 34| 1: [IntLiteral] 5 +# 35| 1: [GotoLabelStmt] goto ...; +# 37| 5: [LabelStmt] done: +# 38| 6: [ExprStmt] ...; +# 38| 0: [MethodCall] call to method WriteLine +# 38| -1: [TypeAccess] access to type Console +# 38| 0: [StringLiteral] "Done" +lock.cs: +# 3| [Class] LockTest +# 5| 5: [Method] A +# 6| 4: [BlockStmt] {...} +# 7| 0: [LocalVariableDeclStmt] ... ...; +# 7| 0: [LocalVariableDeclAndInitExpr] Object object = ... +# 7| 0: [ObjectCreation] object creation of type Object +# 7| 1: [LocalVariableAccess] access to local variable object +# 8| 1: [LockStmt] lock (...) {...} +# 8| 0: [LocalVariableAccess] access to local variable object +# 9| 1: [BlockStmt] {...} +# 10| 0: [ExprStmt] ...; +# 10| 0: [MethodCall] call to method WriteLine +# 10| -1: [TypeAccess] access to type Console +# 10| 0: [MethodCall] call to method ToString +# 10| -1: [LocalVariableAccess] access to local variable object +obj_creation.cs: +# 1| [Class] ObjCreation +# 3| 5: [Class] MyClass +# 5| 4: [Field] x +# 7| 5: [InstanceConstructor] MyClass +# 8| 4: [BlockStmt] {...} +# 11| 6: [InstanceConstructor] MyClass +#-----| 2: (Parameters) +# 11| 0: [Parameter] _x +# 12| 4: [BlockStmt] {...} +# 13| 0: [ExprStmt] ...; +# 13| 0: [AssignExpr] ... = ... +# 13| 0: [ParameterAccess] access to parameter _x +# 13| 1: [FieldAccess] access to field x +# 17| 6: [Method] SomeFun +#-----| 2: (Parameters) +# 17| 0: [Parameter] x +# 18| 4: [BlockStmt] {...} +# 21| 7: [Method] Main +# 22| 4: [BlockStmt] {...} +# 23| 0: [LocalVariableDeclStmt] ... ...; +# 23| 0: [LocalVariableDeclAndInitExpr] MyClass obj = ... +# 23| 0: [ObjectCreation] object creation of type MyClass +# 23| 0: [IntLiteral] 100 +# 23| 1: [LocalVariableAccess] access to local variable obj +# 24| 1: [LocalVariableDeclStmt] ... ...; +# 24| 0: [LocalVariableDeclAndInitExpr] MyClass obj_initlist = ... +# 24| 0: [ObjectCreation] object creation of type MyClass +# 24| -1: [ObjectInitializer] { ..., ... } +# 24| 0: [MemberInitializer] ... = ... +# 24| 0: [IntLiteral] 101 +# 24| 1: [FieldAccess] access to field x +# 24| 1: [LocalVariableAccess] access to local variable obj_initlist +# 25| 2: [LocalVariableDeclStmt] ... ...; +# 25| 0: [LocalVariableDeclAndInitExpr] Int32 a = ... +# 25| 0: [FieldAccess] access to field x +# 25| -1: [LocalVariableAccess] access to local variable obj +# 25| 1: [LocalVariableAccess] access to local variable a +# 27| 3: [ExprStmt] ...; +# 27| 0: [MethodCall] call to method SomeFun +# 27| 0: [ObjectCreation] object creation of type MyClass +# 27| 0: [IntLiteral] 100 +pointers.cs: +# 1| [Class] Pointers +# 3| 5: [Method] addone +#-----| 2: (Parameters) +# 3| 0: [Parameter] arr +# 4| 4: [BlockStmt] {...} +# 5| 0: [LocalVariableDeclStmt] ... ...; +# 5| 0: [LocalVariableDeclAndInitExpr] Int32 length = ... +# 5| 0: [PropertyCall] access to property Length +# 5| -1: [ParameterAccess] access to parameter arr +# 5| 1: [LocalVariableAccess] access to local variable length +# 6| 1: [FixedStmt] fixed(...) { ... } +# 6| -1: [LocalVariableDeclAndInitExpr] Int32* b = ... +# 6| 0: [ParameterAccess] access to parameter arr +# 6| 1: [LocalVariableAccess] access to local variable b +# 7| 0: [BlockStmt] {...} +# 8| 0: [LocalVariableDeclStmt] ... ...; +# 8| 0: [LocalVariableDeclAndInitExpr] Int32* p = ... +# 8| 0: [LocalVariableAccess] access to local variable b +# 8| 1: [LocalVariableAccess] access to local variable p +# 9| 1: [ForStmt] for (...;...;...) ... +# 9| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 9| 0: [IntLiteral] 0 +# 9| 1: [LocalVariableAccess] access to local variable i +# 9| 0: [LTExpr] ... < ... +# 9| 0: [LocalVariableAccess] access to local variable i +# 9| 1: [LocalVariableAccess] access to local variable length +# 9| 1: [PostIncrExpr] ...++ +# 9| 0: [LocalVariableAccess] access to local variable i +# 10| 2: [ExprStmt] ...; +# 10| 0: [AssignAddExpr] ... += ... +# 10| 0: [IntLiteral] 1 +# 10| 1: [PointerIndirectionExpr] *... +# 10| 0: [PostIncrExpr] ...++ +# 10| 0: [LocalVariableAccess] access to local variable p +# 14| 6: [Class] MyClass +# 16| 5: [Field] fld1 +# 17| 6: [Field] fld2 +# 20| 7: [Struct] MyStruct +# 22| 5: [Field] fld +# 25| 8: [Method] Main +# 25| 4: [BlockStmt] {...} +# 26| 0: [LocalVariableDeclStmt] ... ...; +# 26| 0: [LocalVariableDeclAndInitExpr] MyClass o = ... +# 26| 0: [ObjectCreation] object creation of type MyClass +# 26| 1: [LocalVariableAccess] access to local variable o +# 27| 1: [LocalVariableDeclStmt] ... ...; +# 27| 0: [LocalVariableDeclAndInitExpr] MyStruct s = ... +# 27| 0: [ObjectCreation] object creation of type MyStruct +# 27| 1: [LocalVariableAccess] access to local variable s +# 28| 2: [UnsafeStmt] unsafe {...} +# 29| 0: [BlockStmt] {...} +# 30| 0: [FixedStmt] fixed(...) { ... } +# 30| -2: [LocalVariableDeclAndInitExpr] Int32* q = ... +# 30| 0: [AddressOfExpr] &... +# 30| 0: [FieldAccess] access to field fld2 +# 30| -1: [LocalVariableAccess] access to local variable o +# 30| 1: [LocalVariableAccess] access to local variable q +# 30| -1: [LocalVariableDeclAndInitExpr] Int32* p = ... +# 30| 0: [AddressOfExpr] &... +# 30| 0: [FieldAccess] access to field fld1 +# 30| -1: [LocalVariableAccess] access to local variable o +# 30| 1: [LocalVariableAccess] access to local variable p +# 31| 0: [BlockStmt] {...} +# 32| 0: [ExprStmt] ...; +# 32| 0: [AssignExpr] ... = ... +# 32| 0: [IntLiteral] 0 +# 32| 1: [PointerIndirectionExpr] *... +# 32| 0: [LocalVariableAccess] access to local variable p +# 33| 1: [ExprStmt] ...; +# 33| 0: [AssignExpr] ... = ... +# 33| 0: [IntLiteral] 0 +# 33| 1: [PointerIndirectionExpr] *... +# 33| 0: [LocalVariableAccess] access to local variable q +# 34| 2: [LocalVariableDeclStmt] ... ...; +# 34| 0: [LocalVariableDeclAndInitExpr] MyStruct* r = ... +# 34| 0: [AddressOfExpr] &... +# 34| 0: [LocalVariableAccess] access to local variable s +# 34| 1: [LocalVariableAccess] access to local variable r +# 35| 3: [ExprStmt] ...; +# 35| 0: [AssignExpr] ... = ... +# 35| 0: [IntLiteral] 0 +# 35| 1: [FieldAccess] access to field fld +# 35| -1: [PointerIndirectionExpr] *... +# 35| 0: [LocalVariableAccess] access to local variable r +# 39| 3: [LocalVariableDeclStmt] ... ...; +# 39| 0: [LocalVariableDeclAndInitExpr] Int32[] arr = ... +# 39| 0: [ArrayCreation] array creation of type Int32[] +# 39| -1: [ArrayInitializer] { ..., ... } +# 39| 0: [IntLiteral] 1 +# 39| 1: [IntLiteral] 2 +# 39| 2: [IntLiteral] 3 +# 39| 1: [LocalVariableAccess] access to local variable arr +# 40| 4: [ExprStmt] ...; +# 40| 0: [MethodCall] call to method addone +# 40| 0: [LocalVariableAccess] access to local variable arr +prop.cs: +# 1| [Class] PropClass +# 3| 5: [Field] prop +# 5| 6: [Property] Prop +# 7| 3: [Getter] get_Prop +# 8| 4: [BlockStmt] {...} +# 9| 0: [ReturnStmt] return ...; +# 9| 0: [MethodCall] call to method func +# 12| 4: [Setter] set_Prop +#-----| 2: (Parameters) +# 12| 0: [Parameter] value +# 13| 4: [BlockStmt] {...} +# 14| 0: [ExprStmt] ...; +# 14| 0: [AssignExpr] ... = ... +# 14| 0: [ParameterAccess] access to parameter value +# 14| 1: [FieldAccess] access to field prop +# 18| 7: [Method] func +# 19| 4: [BlockStmt] {...} +# 20| 0: [ReturnStmt] return ...; +# 20| 0: [IntLiteral] 0 +# 24| [Class] Prog +# 26| 5: [Method] Main +# 27| 4: [BlockStmt] {...} +# 28| 0: [LocalVariableDeclStmt] ... ...; +# 28| 0: [LocalVariableDeclAndInitExpr] PropClass obj = ... +# 28| 0: [ObjectCreation] object creation of type PropClass +# 28| 1: [LocalVariableAccess] access to local variable obj +# 29| 1: [ExprStmt] ...; +# 29| 0: [AssignExpr] ... = ... +# 29| 0: [IntLiteral] 5 +# 29| 1: [PropertyCall] access to property Prop +# 29| -1: [LocalVariableAccess] access to local variable obj +# 30| 2: [LocalVariableDeclStmt] ... ...; +# 30| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 30| 0: [PropertyCall] access to property Prop +# 30| -1: [LocalVariableAccess] access to local variable obj +# 30| 1: [LocalVariableAccess] access to local variable x +simple_call.cs: +# 3| [Class] test_simple_call +# 5| 5: [Method] f +# 6| 4: [BlockStmt] {...} +# 7| 0: [ReturnStmt] return ...; +# 7| 0: [IntLiteral] 0 +# 10| 6: [Method] g +# 11| 4: [BlockStmt] {...} +# 12| 0: [ReturnStmt] return ...; +# 12| 0: [MethodCall] call to method f +simple_function.cs: +# 3| [Class] test_simple_function +# 5| 5: [Method] f +# 6| 4: [BlockStmt] {...} +# 7| 0: [ReturnStmt] return ...; +# 7| 0: [IntLiteral] 0 +stmts.cs: +# 3| [Class] test_stmts +# 5| 5: [Method] ifStmt +#-----| 2: (Parameters) +# 5| 0: [Parameter] x +# 6| 4: [BlockStmt] {...} +# 7| 0: [IfStmt] if (...) ... +# 7| 0: [EQExpr] ... == ... +# 7| 0: [ParameterAccess] access to parameter x +# 7| 1: [IntLiteral] 5 +# 8| 1: [ReturnStmt] return ...; +# 8| 0: [IntLiteral] 0 +# 10| 2: [ReturnStmt] return ...; +# 10| 0: [IntLiteral] 1 +# 13| 6: [Method] whileStmt +#-----| 2: (Parameters) +# 13| 0: [Parameter] x +# 14| 4: [BlockStmt] {...} +# 15| 0: [LocalVariableDeclStmt] ... ...; +# 15| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 15| 0: [IntLiteral] 0 +# 15| 1: [LocalVariableAccess] access to local variable i +# 16| 1: [WhileStmt] while (...) ... +# 16| 0: [LTExpr] ... < ... +# 16| 0: [LocalVariableAccess] access to local variable i +# 16| 1: [IntLiteral] 10 +# 17| 1: [BlockStmt] {...} +# 18| 0: [ExprStmt] ...; +# 18| 0: [AssignExpr] ... = ... +# 18| 0: [AddExpr] ... + ... +# 18| 0: [ParameterAccess] access to parameter x +# 18| 1: [IntLiteral] 1 +# 18| 1: [ParameterAccess] access to parameter x +# 22| 7: [Method] switchStmt +# 23| 4: [BlockStmt] {...} +# 24| 0: [LocalVariableDeclStmt] ... ...; +# 24| 0: [LocalVariableDeclAndInitExpr] Object caseSwitch = ... +# 24| 0: [ObjectCreation] object creation of type Object +# 24| 1: [LocalVariableAccess] access to local variable caseSwitch +# 25| 1: [LocalVariableDeclStmt] ... ...; +# 25| 0: [LocalVariableDeclAndInitExpr] Int32 select = ... +# 25| 0: [IntLiteral] 0 +# 25| 1: [LocalVariableAccess] access to local variable select +# 27| 2: [SwitchStmt] switch (...) {...} +# 27| 0: [LocalVariableAccess] access to local variable caseSwitch +# 29| 0: [ConstCase] case ...: +# 29| 0: [ConstantPatternExpr,UnaryMinusExpr] -... +# 29| 0: [IntLiteral] 1 +# 30| 1: [GotoCaseStmt] goto case ...; +# 30| 0: [BoolLiteral] true +# 31| 2: [ConstCase] case ...: +# 31| 0: [ConstantPatternExpr,IntLiteral] 0 +# 32| 3: [GotoCaseStmt] goto case ...; +# 32| 0: [StringLiteral] "123" +# 33| 4: [ConstCase] case ...: +# 33| 0: [ConstantPatternExpr,StringLiteral] "123" +# 34| 5: [ExprStmt] ...; +# 34| 0: [AssignExpr] ... = ... +# 34| 0: [IntLiteral] 100 +# 34| 1: [LocalVariableAccess] access to local variable select +# 35| 6: [BreakStmt] break; +# 36| 7: [ConstCase] case ...: +# 36| 0: [BoolLiteral,ConstantPatternExpr] true +# 37| 8: [ExprStmt] ...; +# 37| 0: [AssignExpr] ... = ... +# 37| 0: [IntLiteral] 101 +# 37| 1: [LocalVariableAccess] access to local variable select +# 38| 9: [GotoDefaultStmt] goto default; +# 39| 10: [DefaultCase] default: +# 40| 11: [ReturnStmt] return ...; +# 40| 0: [LocalVariableAccess] access to local variable select +# 42| 3: [ReturnStmt] return ...; +# 42| 0: [IntLiteral] 0 +# 46| 8: [Method] tryCatchFinally +# 47| 4: [BlockStmt] {...} +# 48| 0: [LocalVariableDeclStmt] ... ...; +# 48| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 48| 0: [IntLiteral] 5 +# 48| 1: [LocalVariableAccess] access to local variable x +# 49| 1: [TryStmt] try {...} ... +# 64| -1: [BlockStmt] {...} +# 65| 0: [ExprStmt] ...; +# 65| 0: [AssignExpr] ... = ... +# 65| 0: [IntLiteral] 2 +# 65| 1: [LocalVariableAccess] access to local variable x +# 50| 0: [BlockStmt] {...} +# 51| 0: [IfStmt] if (...) ... +# 51| 0: [NEExpr] ... != ... +# 51| 0: [LocalVariableAccess] access to local variable x +# 51| 1: [IntLiteral] 0 +# 52| 1: [ThrowStmt] throw ...; +# 52| 0: [ObjectCreation] object creation of type Exception +# 53| 1: [ExprStmt] ...; +# 53| 0: [AssignExpr] ... = ... +# 53| 0: [IntLiteral] 0 +# 53| 1: [LocalVariableAccess] access to local variable x +# 55| 1: [SpecificCatchClause] catch (...) {...} +# 55| 0: [LocalVariableDeclExpr] Exception ex +# 56| 1: [BlockStmt] {...} +# 57| 0: [ExprStmt] ...; +# 57| 0: [AssignExpr] ... = ... +# 57| 0: [IntLiteral] 1 +# 57| 1: [LocalVariableAccess] access to local variable x +# 59| 2: [GeneralCatchClause] catch {...} +# 60| 1: [BlockStmt] {...} +# 61| 0: [ThrowStmt] throw ...; +# 69| 9: [Method] forStmt +# 70| 4: [BlockStmt] {...} +# 71| 0: [LocalVariableDeclStmt] ... ...; +# 71| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 71| 0: [IntLiteral] 0 +# 71| 1: [LocalVariableAccess] access to local variable x +# 72| 1: [ForStmt] for (...;...;...) ... +# 72| -2: [LocalVariableDeclAndInitExpr] Int32 j = ... +# 72| 0: [IntLiteral] 10 +# 72| 1: [LocalVariableAccess] access to local variable j +# 72| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 72| 0: [IntLiteral] 0 +# 72| 1: [LocalVariableAccess] access to local variable i +# 72| 0: [LTExpr] ... < ... +# 72| 0: [LocalVariableAccess] access to local variable i +# 72| 1: [LocalVariableAccess] access to local variable j +# 72| 1: [PostIncrExpr] ...++ +# 72| 0: [LocalVariableAccess] access to local variable i +# 72| 2: [PostDecrExpr] ...-- +# 72| 0: [LocalVariableAccess] access to local variable j +# 73| 3: [BlockStmt] {...} +# 74| 0: [ExprStmt] ...; +# 74| 0: [AssignExpr] ... = ... +# 74| 0: [SubExpr] ... - ... +# 74| 0: [LocalVariableAccess] access to local variable x +# 74| 1: [IntLiteral] 1 +# 74| 1: [LocalVariableAccess] access to local variable x +# 77| 2: [LocalVariableDeclStmt] ... ...; +# 77| 0: [LocalVariableDeclExpr] Int32 a +# 77| 1: [LocalVariableDeclAndInitExpr] Int32 b = ... +# 77| 0: [IntLiteral] 10 +# 77| 1: [LocalVariableAccess] access to local variable b +# 78| 3: [ForStmt] for (...;...;...) ... +# 78| -1: [AssignExpr] ... = ... +# 78| 0: [IntLiteral] 0 +# 78| 1: [LocalVariableAccess] access to local variable a +# 78| 0: [LTExpr] ... < ... +# 78| 0: [LocalVariableAccess] access to local variable a +# 78| 1: [LocalVariableAccess] access to local variable b +# 79| 1: [BlockStmt] {...} +# 80| 0: [ExprStmt] ...; +# 80| 0: [PostIncrExpr] ...++ +# 80| 0: [LocalVariableAccess] access to local variable a +# 83| 4: [ForStmt] for (...;...;...) ... +# 84| 1: [BlockStmt] {...} +# 89| 10: [Method] doWhile +# 90| 4: [BlockStmt] {...} +# 91| 0: [LocalVariableDeclStmt] ... ...; +# 91| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 91| 0: [IntLiteral] 0 +# 91| 1: [LocalVariableAccess] access to local variable x +# 92| 1: [DoStmt] do ... while (...); +# 96| 0: [LTExpr] ... < ... +# 96| 0: [LocalVariableAccess] access to local variable x +# 96| 1: [IntLiteral] 10 +# 93| 1: [BlockStmt] {...} +# 94| 0: [ExprStmt] ...; +# 94| 0: [AssignExpr] ... = ... +# 94| 0: [AddExpr] ... + ... +# 94| 0: [LocalVariableAccess] access to local variable x +# 94| 1: [IntLiteral] 1 +# 94| 1: [LocalVariableAccess] access to local variable x +# 99| 11: [Method] checkedUnchecked +# 100| 4: [BlockStmt] {...} +# 101| 0: [LocalVariableDeclStmt] ... ...; +# 101| 0: [LocalVariableDeclAndInitExpr] Int32 num = ... +# 101| 0: [MemberConstantAccess] access to constant MaxValue +# 101| -1: [TypeAccess] access to type Int32 +# 101| 1: [LocalVariableAccess] access to local variable num +# 102| 1: [UncheckedStmt] unchecked {...} +# 103| 0: [BlockStmt] {...} +# 104| 0: [ExprStmt] ...; +# 104| 0: [AssignExpr] ... = ... +# 104| 0: [AddExpr] ... + ... +# 104| 0: [LocalVariableAccess] access to local variable num +# 104| 1: [IntLiteral] 1 +# 104| 1: [LocalVariableAccess] access to local variable num +# 106| 2: [CheckedStmt] checked {...} +# 107| 0: [BlockStmt] {...} +# 108| 0: [ExprStmt] ...; +# 108| 0: [AssignExpr] ... = ... +# 108| 0: [AddExpr] ... + ... +# 108| 0: [LocalVariableAccess] access to local variable num +# 108| 1: [IntLiteral] 1 +# 108| 1: [LocalVariableAccess] access to local variable num +using.cs: +# 3| [Class] UsingStmt +# 5| 5: [Class] MyDisposable +#-----| 3: (Base types) +# 5| 1: [Interface] IDisposable +# 7| 4: [InstanceConstructor] MyDisposable +# 7| 4: [BlockStmt] {...} +# 8| 5: [Method] DoSomething +# 8| 4: [BlockStmt] {...} +# 9| 6: [Method] Dispose +# 9| 4: [BlockStmt] {...} +# 12| 6: [Method] Main +# 13| 4: [BlockStmt] {...} +# 14| 0: [UsingBlockStmt] using (...) {...} +# 14| -1: [LocalVariableDeclAndInitExpr] MyDisposable o1 = ... +# 14| 0: [ObjectCreation] object creation of type MyDisposable +# 14| 1: [LocalVariableAccess] access to local variable o1 +# 15| 1: [BlockStmt] {...} +# 16| 0: [ExprStmt] ...; +# 16| 0: [MethodCall] call to method DoSomething +# 16| -1: [LocalVariableAccess] access to local variable o1 +# 19| 1: [LocalVariableDeclStmt] ... ...; +# 19| 0: [LocalVariableDeclAndInitExpr] MyDisposable o2 = ... +# 19| 0: [ObjectCreation] object creation of type MyDisposable +# 19| 1: [LocalVariableAccess] access to local variable o2 +# 20| 2: [UsingBlockStmt] using (...) {...} +# 20| 0: [LocalVariableAccess] access to local variable o2 +# 21| 1: [BlockStmt] {...} +# 22| 0: [ExprStmt] ...; +# 22| 0: [MethodCall] call to method DoSomething +# 22| -1: [LocalVariableAccess] access to local variable o2 +# 25| 3: [UsingDeclStmt] using ... ...; +# 25| 0: [LocalVariableDeclAndInitExpr] MyDisposable o3 = ... +# 25| 0: [ObjectCreation] object creation of type MyDisposable +# 25| 1: [LocalVariableAccess] access to local variable o3 +# 26| 4: [ExprStmt] ...; +# 26| 0: [MethodCall] call to method DoSomething +# 26| -1: [LocalVariableAccess] access to local variable o3 +variables.cs: +# 3| [Class] test_variables +# 5| 5: [Method] f +# 6| 4: [BlockStmt] {...} +# 7| 0: [LocalVariableDeclStmt] ... ...; +# 7| 0: [LocalVariableDeclExpr] Int32 x +# 7| 1: [LocalVariableDeclAndInitExpr] Int32 y = ... +# 7| 0: [IntLiteral] 5 +# 7| 1: [LocalVariableAccess] access to local variable y +# 8| 1: [ExprStmt] ...; +# 8| 0: [AssignExpr] ... = ... +# 8| 0: [IntLiteral] 4 +# 8| 1: [LocalVariableAccess] access to local variable x +# 9| 2: [ExprStmt] ...; +# 9| 0: [AssignExpr] ... = ... +# 9| 0: [LocalVariableAccess] access to local variable y +# 9| 1: [LocalVariableAccess] access to local variable x +# 10| 3: [LocalVariableDeclStmt] ... ...; +# 10| 0: [LocalVariableDeclAndInitExpr] Int32 z = ... +# 10| 0: [LocalVariableAccess] access to local variable y +# 10| 1: [LocalVariableAccess] access to local variable z diff --git a/csharp/ql/test/experimental/ir/ir/PrintAst.qlref b/csharp/ql/test/experimental/ir/ir/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/experimental/ir/ir/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/arguments/PrintAst.expected b/csharp/ql/test/library-tests/arguments/PrintAst.expected new file mode 100644 index 00000000000..528cfa5ca3e --- /dev/null +++ b/csharp/ql/test/library-tests/arguments/PrintAst.expected @@ -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] {...} diff --git a/csharp/ql/test/library-tests/arguments/PrintAst.qlref b/csharp/ql/test/library-tests/arguments/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/arguments/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/assignments/PrintAst.expected b/csharp/ql/test/library-tests/assignments/PrintAst.expected new file mode 100644 index 00000000000..5ed80924814 --- /dev/null +++ b/csharp/ql/test/library-tests/assignments/PrintAst.expected @@ -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 diff --git a/csharp/ql/test/library-tests/assignments/PrintAst.qlref b/csharp/ql/test/library-tests/assignments/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/assignments/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/attributes/PrintAst.expected b/csharp/ql/test/library-tests/attributes/PrintAst.expected new file mode 100644 index 00000000000..87114afe0cb --- /dev/null +++ b/csharp/ql/test/library-tests/attributes/PrintAst.expected @@ -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 � 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] {...} diff --git a/csharp/ql/test/library-tests/attributes/PrintAst.qlref b/csharp/ql/test/library-tests/attributes/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/attributes/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/constructors/PrintAst.expected b/csharp/ql/test/library-tests/constructors/PrintAst.expected new file mode 100644 index 00000000000..84a08a3522e --- /dev/null +++ b/csharp/ql/test/library-tests/constructors/PrintAst.expected @@ -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 diff --git a/csharp/ql/test/library-tests/constructors/PrintAst.qlref b/csharp/ql/test/library-tests/constructors/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/constructors/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/conversion/operator/PrintAst.expected b/csharp/ql/test/library-tests/conversion/operator/PrintAst.expected new file mode 100644 index 00000000000..9ce74d7c956 --- /dev/null +++ b/csharp/ql/test/library-tests/conversion/operator/PrintAst.expected @@ -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 diff --git a/csharp/ql/test/library-tests/conversion/operator/PrintAst.qlref b/csharp/ql/test/library-tests/conversion/operator/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/conversion/operator/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp6/PrintAst.expected b/csharp/ql/test/library-tests/csharp6/PrintAst.expected new file mode 100644 index 00000000000..92a1d2f8709 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp6/PrintAst.expected @@ -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 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 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 testElementBinding = ... +# 32| 0: [IndexerCall] access to indexer +# 32| -1: [IndexerCall] access to indexer +# 32| -1: [ObjectCreation] object creation of type Dictionary +# 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 dict = ... +# 68| 0: [ObjectCreation] object creation of type Dictionary +# 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 diff --git a/csharp/ql/test/library-tests/csharp6/PrintAst.qlref b/csharp/ql/test/library-tests/csharp6/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/csharp6/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp7.1/PrintAst.expected b/csharp/ql/test/library-tests/csharp7.1/PrintAst.expected new file mode 100644 index 00000000000..381ae9dee74 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp7.1/PrintAst.expected @@ -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 diff --git a/csharp/ql/test/library-tests/csharp7.1/PrintAst.qlref b/csharp/ql/test/library-tests/csharp7.1/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/csharp7.1/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp7.2/PrintAst.expected b/csharp/ql/test/library-tests/csharp7.2/PrintAst.expected new file mode 100644 index 00000000000..03f61e18065 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp7.2/PrintAst.expected @@ -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 diff --git a/csharp/ql/test/library-tests/csharp7.2/PrintAst.qlref b/csharp/ql/test/library-tests/csharp7.2/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/csharp7.2/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected b/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected new file mode 100644 index 00000000000..81e247bfb4f --- /dev/null +++ b/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected @@ -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 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 diff --git a/csharp/ql/test/library-tests/csharp7.3/PrintAst.qlref b/csharp/ql/test/library-tests/csharp7.3/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/csharp7.3/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp7/PrintAst.expected b/csharp/ql/test/library-tests/csharp7/PrintAst.expected new file mode 100644 index 00000000000..eb89509351f --- /dev/null +++ b/csharp/ql/test/library-tests/csharp7/PrintAst.expected @@ -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 f4 = ... +# 135| 0: [ImplicitDelegateCreation] delegate creation of type Func +# 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 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 dict = ... +# 283| 0: [ObjectCreation] object creation of type Dictionary +# 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 diff --git a/csharp/ql/test/library-tests/csharp7/PrintAst.qlref b/csharp/ql/test/library-tests/csharp7/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/csharp7/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp8/PrintAst.expected b/csharp/ql/test/library-tests/csharp8/PrintAst.expected new file mode 100644 index 00000000000..d0c199b74bd --- /dev/null +++ b/csharp/ql/test/library-tests/csharp8/PrintAst.expected @@ -0,0 +1,1092 @@ +AlternateInterpolatedStrings.cs: +# 3| [Class] AlternateInterpolatedStrings +# 5| 5: [Field] s1 +# 5| 1: [AssignExpr] ... = ... +# 5| 0: [InterpolatedStringExpr] $"..." +# 5| 0: [StringLiteral] "C:" +# 5| 1: [IntLiteral] 12 +# 5| 1: [FieldAccess] access to field s1 +# 6| 6: [Field] s2 +# 6| 1: [AssignExpr] ... = ... +# 6| 0: [InterpolatedStringExpr] $"..." +# 6| 0: [StringLiteral] "C:" +# 6| 1: [IntLiteral] 12 +# 6| 1: [FieldAccess] access to field s2 +AsyncStreams.cs: +# 24| [NamespaceDeclaration] namespace ... { ... } +# 26| 1: [Interface] IAsyncDisposable +# 28| 4: [Method] DisposeAsync +# 32| [NamespaceDeclaration] namespace ... { ... } +# 34| 1: [Interface] IAsyncEnumerable<> +#-----| 1: (Type parameters) +# 34| 0: [TypeParameter] T +# 36| 4: [Method] GetAsyncEnumerator +#-----| 2: (Parameters) +# 36| 0: [Parameter] cancellationToken +# 36| 1: [DefaultValueExpr] default(...) +# 36| 0: [TypeAccess] access to type CancellationToken +# 39| 2: [Interface] IAsyncEnumerator<> +#-----| 1: (Type parameters) +# 39| 0: [TypeParameter] T +#-----| 3: (Base types) +# 39| 1: [Interface] IAsyncDisposable +# 41| 4: [Property] Current +# 41| 3: [Getter] get_Current +# 42| 5: [Method] MoveNextAsync +# 8| [Class] AsyncStreams +# 10| 5: [Method] Items +# 10| 4: [BlockStmt] {...} +# 11| 0: [YieldReturnStmt] yield return ...; +# 11| 0: [IntLiteral] 1 +# 12| 1: [YieldReturnStmt] yield return ...; +# 12| 0: [IntLiteral] 2 +# 13| 2: [ExprStmt] ...; +# 13| 0: [AwaitExpr] await ... +# 13| 0: [MethodCall] call to method Delay +# 13| -1: [TypeAccess] access to type Task +# 13| 0: [IntLiteral] 1000 +# 14| 3: [YieldReturnStmt] yield return ...; +# 14| 0: [IntLiteral] 3 +# 17| 6: [Method] F +# 18| 4: [BlockStmt] {...} +# 19| 0: [ForeachStmt] foreach (... ... in ...) ... +# 19| 0: [LocalVariableDeclExpr] Int32 item +# 19| 1: [MethodCall] call to method Items +# 20| 2: [ExprStmt] ...; +# 20| 0: [MethodCall] call to method WriteLine +# 20| -1: [TypeAccess] access to type Console +# 20| 0: [LocalVariableAccess] access to local variable item +DefaultInterfaceMethods.cs: +# 3| [Interface] IPerson +# 5| 4: [IndexerProperty] Name +# 5| 3: [Getter] get_Name +# 7| 5: [IndexerProperty] Greeting +# 9| 3: [Getter] get_Greeting +# 9| 4: [StringLiteral] "Hello" +# 10| 4: [Setter] set_Greeting +#-----| 2: (Parameters) +# 10| 0: [Parameter] value +# 10| 4: [BlockStmt] {...} +# 13| 6: [Method] Greet +#-----| 2: (Parameters) +# 13| 0: [Parameter] name +# 13| 4: [AddExpr] ... + ... +# 13| 0: [AddExpr] ... + ... +# 13| 0: [PropertyCall] access to property Greeting +# 13| 1: [StringLiteral] " " +# 13| 1: [ParameterAccess] access to parameter name +# 15| 7: [IndexerProperty] GreetingString +# 15| 3: [Getter] get_GreetingString +# 15| 4: [MethodCall] call to method Greet +# 15| 0: [PropertyCall] access to property Name +# 17| 8: [Method] Greet +# 20| [Class] Person +#-----| 3: (Base types) +# 20| 1: [Interface] IPerson +# 22| 5: [IndexerProperty] Name +# 22| 3: [Getter] get_Name +# 22| 4: [StringLiteral] "Petra" +# 24| 6: [IndexerProperty] Greeting +# 24| 3: [Getter] get_Greeting +# 24| 4: [StringLiteral] "Howdy" +# 24| 4: [Setter] set_Greeting +#-----| 2: (Parameters) +# 24| 0: [Parameter] value +# 24| 4: [BlockStmt] {...} +# 26| 7: [Method] Greet +# 26| 4: [BlockStmt] {...} +NullCoalescingAssignment.cs: +# 3| [Class] NullCoalescingAssignment +# 5| 5: [Method] NullCoalescing +# 6| 4: [BlockStmt] {...} +# 7| 0: [LocalVariableDeclStmt] ... ...; +# 7| 0: [LocalVariableDeclAndInitExpr] Object o = ... +# 7| 0: [NullLiteral] null +# 7| 1: [LocalVariableAccess] access to local variable o +# 8| 1: [ExprStmt] ...; +# 8| 0: [AssignCoalesceExpr] ... ??= ... +# 8| 0: [ThisAccess] this access +# 8| 1: [LocalVariableAccess] access to local variable o +NullableRefTypes.cs: +# 6| [Class] MyClass +# 9| 5: [Field] A +# 10| 6: [Field] B +# 13| 7: [IndexerProperty] C +# 13| 3: [Getter] get_C +# 13| 4: [NullLiteral] null +# 14| 8: [IndexerProperty] D +# 14| 3: [Getter] get_D +# 14| 4: [ThisAccess] this access +# 17| 9: [Indexer] Item +#-----| 1: (Parameters) +# 17| 0: [Parameter] i +# 17| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 17| 0: [Parameter] i +# 17| 4: [NullLiteral] null +# 18| 10: [Indexer] Item +#-----| 1: (Parameters) +# 18| 0: [Parameter] i +# 18| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 18| 0: [Parameter] i +# 18| 4: [ThisAccess] this access +# 19| 11: [Indexer] Item +#-----| 1: (Parameters) +# 19| 0: [Parameter] i +# 19| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 19| 0: [Parameter] i +# 19| 4: [ThisAccess] this access +# 22| 12: [Field] G1 +# 23| 13: [Field] G2 +# 24| 14: [Field] G3 +# 25| 15: [Field] H +# 26| 16: [Method] ArrayFn1 +#-----| 2: (Parameters) +# 26| 0: [Parameter] x +# 26| 4: [ThrowExpr] throw ... +# 26| 0: [NullLiteral] null +# 27| 17: [Method] ArrayFn2 +#-----| 2: (Parameters) +# 27| 0: [Parameter] x +# 27| 4: [ThrowExpr] throw ... +# 27| 0: [NullLiteral] null +# 30| 18: [Method] M +# 30| 4: [NullLiteral] null +# 31| 19: [Method] N +# 31| 4: [ThisAccess] this access +# 32| 20: [Method] O +#-----| 2: (Parameters) +# 32| 0: [Parameter] a +# 32| 1: [Parameter] b +# 32| 4: [BlockStmt] {...} +# 35| 21: [Method] Locals +# 36| 4: [BlockStmt] {...} +# 37| 0: [LocalVariableDeclStmt] ... ...; +# 37| 0: [LocalVariableDeclAndInitExpr] MyClass a = ... +# 37| 0: [ObjectCreation] object creation of type MyClass +# 37| 1: [LocalVariableAccess] access to local variable a +# 38| 1: [LocalVariableDeclStmt] ... ...; +# 38| 0: [LocalVariableDeclAndInitExpr] MyClass b = ... +# 38| 0: [NullLiteral] null +# 38| 1: [LocalVariableAccess] access to local variable b +# 39| 2: [LocalVariableDeclStmt] ... ...; +# 39| 0: [LocalVariableDeclAndInitExpr] MyClass c = ... +# 39| 0: [RefExpr] ref ... +# 39| 0: [LocalVariableAccess] access to local variable b +# 39| 1: [LocalVariableAccess] access to local variable c +# 40| 3: [LocalVariableDeclStmt] ... ...; +# 40| 0: [LocalVariableDeclAndInitExpr] MyClass d = ... +# 40| 0: [RefExpr] ref ... +# 40| 0: [LocalVariableAccess] access to local variable b +# 40| 1: [LocalVariableAccess] access to local variable d +# 44| 22: [DelegateType] Del1 +# 47| 23: [DelegateType] Del +#-----| 2: (Parameters) +# 47| 0: [Parameter] x +# 48| 24: [Event] P +# 48| 3: [AddEventAccessor] add_P +#-----| 2: (Parameters) +# 48| 0: [Parameter] value +# 48| 3: [RemoveEventAccessor] remove_P +#-----| 2: (Parameters) +# 48| 0: [Parameter] value +# 51| 25: [Method] Q +#-----| 1: (Type parameters) +# 51| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 51| 0: [Parameter] t +# 51| 4: [NullLiteral] null +# 54| 27: [Class] Generic<,,,> +#-----| 1: (Type parameters) +# 54| 0: [TypeParameter] T1 +# 54| 1: [TypeParameter] T2 +# 54| 2: [TypeParameter] T3 +# 54| 3: [TypeParameter] T4 +# 58| 30: [Class] Generic2<,> +#-----| 1: (Type parameters) +# 58| 0: [TypeParameter] T1 +# 58| 1: [TypeParameter] T2 +# 65| 31: [Field] items2 +# 67| 32: [Method] GenericFn +#-----| 1: (Type parameters) +# 67| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 67| 0: [Parameter] x +# 68| 4: [BlockStmt] {...} +# 71| 34: [Method] CallF +# 72| 4: [BlockStmt] {...} +# 73| 0: [LocalVariableDeclStmt] ... ...; +# 73| 0: [LocalVariableDeclAndInitExpr] MyClass x = ... +# 73| 0: [NullLiteral] null +# 73| 1: [LocalVariableAccess] access to local variable x +# 74| 1: [ExprStmt] ...; +# 74| 0: [MethodCall] call to method GenericFn +# 74| 0: [LocalVariableAccess] access to local variable x +# 75| 2: [ExprStmt] ...; +# 75| 0: [MethodCall] call to method Q +# 75| 0: [LocalVariableAccess] access to local variable x +# 76| 3: [ReturnStmt] return ...; +# 76| 0: [DefaultValueExpr] default(...) +# 76| 0: [TypeAccess] access to type MyStruct +# 80| [Class] NullableRefTypes +# 82| 5: [Method] TestSuppressNullableWarningExpr +# 83| 4: [BlockStmt] {...} +# 84| 0: [LocalVariableDeclStmt] ... ...; +# 84| 0: [LocalVariableDeclAndInitExpr] String x = ... +# 84| 0: [StringLiteral] "source" +# 84| 1: [LocalVariableAccess] access to local variable x +# 85| 1: [LocalVariableDeclStmt] ... ...; +# 85| 0: [LocalVariableDeclAndInitExpr] String y = ... +# 85| 0: [SuppressNullableWarningExpr] ...! +# 85| 0: [LocalVariableAccess] access to local variable x +# 85| 1: [LocalVariableAccess] access to local variable y +# 86| 2: [ExprStmt] ...; +# 86| 0: [AssignExpr] ... = ... +# 86| 0: [SuppressNullableWarningExpr] ...! +# 86| 0: [LocalVariableAccess] access to local variable x +# 86| 1: [LocalVariableAccess] access to local variable y +# 87| 3: [ExprStmt] ...; +# 87| 0: [AssignExpr] ... = ... +# 87| 0: [NullLiteral] null +# 87| 1: [LocalVariableAccess] access to local variable x +# 88| 4: [ExprStmt] ...; +# 88| 0: [AssignExpr] ... = ... +# 88| 0: [SuppressNullableWarningExpr] ...! +# 88| 0: [LocalVariableAccess] access to local variable x +# 88| 1: [LocalVariableAccess] access to local variable y +# 91| 6: [Method] FunctionInNullableContext +# 92| 4: [BlockStmt] {...} +# 93| 0: [LocalVariableDeclStmt] ... ...; +# 93| 0: [LocalVariableDeclAndInitExpr] String x = ... +# 93| 0: [StringLiteral] "source" +# 93| 1: [LocalVariableAccess] access to local variable x +# 94| 1: [LocalVariableDeclStmt] ... ...; +# 94| 0: [LocalVariableDeclAndInitExpr] String y = ... +# 94| 0: [NullCoalescingExpr] ... ?? ... +# 94| 0: [LocalVariableAccess] access to local variable x +# 94| 1: [NullLiteral] null +# 94| 1: [LocalVariableAccess] access to local variable y +# 95| 2: [LocalVariableDeclStmt] ... ...; +# 95| 0: [LocalVariableDeclAndInitExpr] String z = ... +# 95| 0: [LocalVariableAccess] access to local variable x +# 95| 1: [LocalVariableAccess] access to local variable z +# 96| 3: [ExprStmt] ...; +# 96| 0: [MethodCall] call to method WriteLine +# 96| -1: [TypeAccess] access to type Console +# 96| 0: [LocalVariableAccess] access to local variable x +# 100| [Class] RefTypes +# 103| 5: [Method] ReturnsRef1 +#-----| 2: (Parameters) +# 103| 0: [Parameter] r +# 103| 4: [RefExpr] ref ... +# 103| 0: [ParameterAccess] access to parameter r +# 104| 6: [Method] ReturnsRef2 +#-----| 2: (Parameters) +# 104| 0: [Parameter] r +# 104| 4: [RefExpr] ref ... +# 104| 0: [ParameterAccess] access to parameter r +# 105| 7: [Method] ReturnsRef3 +#-----| 2: (Parameters) +# 105| 0: [Parameter] r +# 105| 4: [RefExpr] ref ... +# 105| 0: [ParameterAccess] access to parameter r +# 106| 8: [Method] ReturnsRef4 +#-----| 2: (Parameters) +# 106| 0: [Parameter] r +# 106| 4: [RefExpr] ref ... +# 106| 0: [ParameterAccess] access to parameter r +# 107| 9: [Method] ReturnsRef5 +#-----| 2: (Parameters) +# 107| 0: [Parameter] r +# 107| 4: [RefExpr] ref ... +# 107| 0: [ParameterAccess] access to parameter r +# 108| 10: [Method] ReturnsRef6 +#-----| 2: (Parameters) +# 108| 0: [Parameter] r +# 108| 4: [RefExpr] ref ... +# 108| 0: [ParameterAccess] access to parameter r +# 110| 11: [Method] Parameters1 +#-----| 2: (Parameters) +# 110| 0: [Parameter] p1 +# 110| 1: [Parameter] p2 +# 110| 4: [ThrowExpr] throw ... +# 110| 0: [NullLiteral] null +# 112| 12: [Field] Property +# 113| 13: [IndexerProperty] RefProperty +# 113| 3: [Getter] get_RefProperty +# 113| 4: [RefExpr] ref ... +# 113| 0: [SuppressNullableWarningExpr] ...! +# 113| 0: [FieldAccess] access to field Property +# 116| [Class] ToStringWithTypes +# 118| 5: [Field] a +# 119| 6: [Field] b +# 120| 7: [Field] c +# 121| 8: [Field] d +# 123| 9: [Field] e +# 124| 10: [Field] f +# 125| 11: [Field] g +# 126| 12: [Field] h +# 128| 13: [Field] i +# 129| 14: [Field] j +# 130| 15: [Field] k +# 131| 16: [Field] l +# 165| [Struct] MyStruct +# 136| [Class] ToStringWithTypes2 +# 138| 5: [Field] a +# 139| 6: [Field] b +# 140| 7: [Field] c +# 141| 8: [Field] d +# 143| 9: [Field] e +# 144| 10: [Field] f +# 145| 11: [Field] g +# 146| 12: [Field] h +# 148| 13: [Field] i +# 149| 14: [Field] j +# 150| 15: [Field] k +# 151| 16: [Field] l +# 154| [Class] DisabledNullability +# 156| 5: [Field] f1 +# 157| 6: [IndexerProperty] P +# 157| 3: [Getter] get_P +# 157| 4: [ObjectCreation] object creation of type MyClass +# 158| 7: [Method] Fn +#-----| 2: (Parameters) +# 158| 0: [Parameter] p +# 159| 4: [BlockStmt] {...} +# 160| 0: [LocalVariableDeclStmt] ... ...; +# 160| 0: [LocalVariableDeclAndInitExpr] MyClass a = ... +# 160| 0: [ParameterAccess] access to parameter p +# 160| 1: [LocalVariableAccess] access to local variable a +# 161| 1: [ReturnStmt] return ...; +# 161| 0: [LocalVariableAccess] access to local variable a +# 171| [Class] TestNullableFlowStates +# 173| 5: [Method] MaybeNull +# 175| 6: [Method] Check +#-----| 2: (Parameters) +# 175| 0: [Parameter] isNull +# 177| 7: [Method] Count +# 179| 8: [Method] LoopUnrolling +# 180| 4: [BlockStmt] {...} +# 181| 0: [LocalVariableDeclStmt] ... ...; +# 181| 0: [LocalVariableDeclAndInitExpr] String x = ... +# 181| 0: [MethodCall] call to method MaybeNull +# 181| 1: [LocalVariableAccess] access to local variable x +# 183| 1: [ExprStmt] ...; +# 183| 0: [MethodCall] call to method Check +# 183| 0: [LocalVariableAccess] access to local variable x +# 185| 2: [ForStmt] for (...;...;...) ... +# 185| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 185| 0: [IntLiteral] 0 +# 185| 1: [LocalVariableAccess] access to local variable i +# 185| 0: [LTExpr] ... < ... +# 185| 0: [LocalVariableAccess] access to local variable i +# 185| 1: [IntLiteral] 10 +# 185| 1: [PreIncrExpr] ++... +# 185| 0: [LocalVariableAccess] access to local variable i +# 186| 2: [BlockStmt] {...} +# 187| 0: [ExprStmt] ...; +# 187| 0: [AssignExpr] ... = ... +# 187| 0: [StringLiteral] "not null any more" +# 187| 1: [LocalVariableAccess] access to local variable x +# 190| 3: [ExprStmt] ...; +# 190| 0: [MethodCall] call to method Check +# 190| 0: [LocalVariableAccess] access to local variable x +# 193| 9: [Method] ExceptionFlow +# 194| 4: [BlockStmt] {...} +# 195| 0: [LocalVariableDeclStmt] ... ...; +# 195| 0: [LocalVariableDeclAndInitExpr] String y = ... +# 195| 0: [MethodCall] call to method MaybeNull +# 195| 1: [LocalVariableAccess] access to local variable y +# 197| 1: [TryStmt] try {...} ... +# 202| -1: [BlockStmt] {...} +# 203| 0: [ExprStmt] ...; +# 203| 0: [AssignExpr] ... = ... +# 203| 0: [StringLiteral] "not null" +# 203| 1: [LocalVariableAccess] access to local variable y +# 198| 0: [BlockStmt] {...} +# 199| 0: [ThrowStmt] throw ...; +# 199| 0: [ObjectCreation] object creation of type ArgumentException +# 206| 2: [ExprStmt] ...; +# 206| 0: [MethodCall] call to method Check +# 206| 0: [LocalVariableAccess] access to local variable y +# 209| 10: [Method] InvocationTest +#-----| 2: (Parameters) +# 209| 0: [Parameter] o +# 210| 4: [BlockStmt] {...} +# 211| 0: [LocalVariableDeclStmt] ... ...; +# 211| 0: [LocalVariableDeclAndInitExpr] Type t = ... +# 211| 0: [MethodCall] call to method GetType +# 211| -1: [ParameterAccess] access to parameter o +# 211| 1: [LocalVariableAccess] access to local variable t +# 212| 1: [ReturnStmt] return ...; +# 212| 0: [MethodCall] call to method ToString +# 212| -1: [LocalVariableAccess] access to local variable t +# 215| 11: [Method] ElementTest +#-----| 2: (Parameters) +# 215| 0: [Parameter] list +# 216| 4: [BlockStmt] {...} +# 217| 0: [LocalVariableDeclStmt] ... ...; +# 217| 0: [LocalVariableDeclAndInitExpr] String a = ... +# 217| 0: [FieldAccess] access to field Field +# 217| -1: [MethodCall] call to method GetSelf +# 217| 1: [LocalVariableAccess] access to local variable a +# 218| 1: [LocalVariableDeclStmt] ... ...; +# 218| 0: [LocalVariableDeclAndInitExpr] String b = ... +# 218| 0: [IndexerCall] access to indexer +# 218| -1: [ParameterAccess] access to parameter list +# 218| 0: [IntLiteral] 0 +# 218| 1: [LocalVariableAccess] access to local variable b +# 219| 2: [LocalVariableDeclStmt] ... ...; +# 219| 0: [LocalVariableDeclAndInitExpr] String c = ... +# 219| 0: [IndexerCall] access to indexer +# 219| -1: [ParameterAccess] access to parameter list +# 219| 0: [IntLiteral] 0 +# 219| 1: [LocalVariableAccess] access to local variable c +# 220| 3: [LocalVariableDeclStmt] ... ...; +# 220| 0: [LocalVariableDeclAndInitExpr] String d = ... +# 220| 0: [FieldAccess] access to field Field +# 220| -1: [MethodCall] call to method GetSelf +# 220| 1: [LocalVariableAccess] access to local variable d +# 223| 12: [Method] GetSelf +# 225| 13: [Field] Field +StaticLocalFunctions.cs: +# 5| [Class] StaticLocalFunctions +# 7| 5: [Method] Fn +#-----| 2: (Parameters) +# 7| 0: [Parameter] x +# 8| 4: [BlockStmt] {...} +# 9| 0: [LocalFunctionStmt] I(...) +# 9| 0: [LocalFunction] I +#-----| 2: (Parameters) +# 9| 0: [Parameter] y +# 9| 4: [ParameterAccess] access to parameter y +# 10| 1: [LocalFunctionStmt] J(...) +# 10| 0: [LocalFunction] J +#-----| 2: (Parameters) +# 10| 0: [Parameter] y +# 10| 4: [AddExpr] ... + ... +# 10| 0: [ParameterAccess] access to parameter x +# 10| 1: [ParameterAccess] access to parameter y +# 11| 2: [ReturnStmt] return ...; +# 11| 0: [AddExpr] ... + ... +# 11| 0: [LocalFunctionCall] call to local function I +# 11| -1: [LocalFunctionAccess] access to local function I +# 11| 0: [ParameterAccess] access to parameter x +# 11| 1: [LocalFunctionCall] call to local function J +# 11| -1: [LocalFunctionAccess] access to local function J +# 11| 0: [ParameterAccess] access to parameter x +UnmanagedGenericStructs.cs: +# 3| [Struct] S<,> +#-----| 1: (Type parameters) +# 3| 0: [TypeParameter] T +# 3| 1: [TypeParameter] U +# 5| 5: [Field] id +# 6| 6: [Field] value1 +# 7| 7: [Field] value2 +UsingDeclarations.cs: +# 4| [Class] UsingDeclarations +# 6| 5: [Method] TestUsingDeclarations +# 7| 4: [BlockStmt] {...} +# 8| 0: [UsingDeclStmt] using ... ...; +# 8| 0: [LocalVariableDeclAndInitExpr] FileStream file1 = ... +# 8| 0: [ObjectCreation] object creation of type FileStream +# 8| 0: [StringLiteral] "..." +# 8| 1: [MemberConstantAccess] access to constant Open +# 8| -1: [TypeAccess] access to type FileMode +# 8| 1: [LocalVariableAccess] access to local variable file1 +# 8| 1: [LocalVariableDeclAndInitExpr] FileStream file2 = ... +# 8| 0: [ObjectCreation] object creation of type FileStream +# 8| 0: [StringLiteral] "..." +# 8| 1: [MemberConstantAccess] access to constant Open +# 8| -1: [TypeAccess] access to type FileMode +# 8| 1: [LocalVariableAccess] access to local variable file2 +# 10| 1: [UsingBlockStmt] using (...) {...} +# 10| -2: [LocalVariableDeclAndInitExpr] FileStream file4 = ... +# 10| 0: [ObjectCreation] object creation of type FileStream +# 10| 0: [StringLiteral] "..." +# 10| 1: [MemberConstantAccess] access to constant Open +# 10| -1: [TypeAccess] access to type FileMode +# 10| 1: [LocalVariableAccess] access to local variable file4 +# 10| -1: [LocalVariableDeclAndInitExpr] FileStream file3 = ... +# 10| 0: [ObjectCreation] object creation of type FileStream +# 10| 0: [StringLiteral] "..." +# 10| 1: [MemberConstantAccess] access to constant Open +# 10| -1: [TypeAccess] access to type FileMode +# 10| 1: [LocalVariableAccess] access to local variable file3 +# 11| 1: [BlockStmt] {...} +# 14| 2: [UsingBlockStmt] using (...) {...} +# 14| 0: [ObjectCreation] object creation of type FileStream +# 14| 0: [StringLiteral] "..." +# 14| 1: [MemberConstantAccess] access to constant Open +# 14| -1: [TypeAccess] access to type FileMode +# 15| 1: [EmptyStmt] ; +patterns.cs: +# 3| [Class] Patterns +# 5| 5: [Method] IsPatterns +# 6| 4: [BlockStmt] {...} +# 7| 0: [LocalVariableDeclStmt] ... ...; +# 7| 0: [LocalVariableDeclAndInitExpr] Object o = ... +# 7| 0: [CastExpr] (...) ... +# 7| 0: [ObjectCreation] object creation of type MyStruct +# 7| -1: [ObjectInitializer] { ..., ... } +# 7| 0: [MemberInitializer] ... = ... +# 7| 0: [IntLiteral] 2 +# 7| 1: [FieldAccess] access to field X +# 7| 1: [LocalVariableAccess] access to local variable o +# 9| 1: [IfStmt] if (...) ... +# 9| 0: [IsExpr] ... is ... +# 9| 0: [LocalVariableAccess] access to local variable o +# 9| 1: [VariablePatternExpr] MyStruct ms1 +# 10| 1: [BlockStmt] {...} +# 13| 2: [IfStmt] if (...) ... +# 13| 0: [LogicalAndExpr] ... && ... +# 13| 0: [LogicalAndExpr] ... && ... +# 13| 0: [IsExpr] ... is ... +# 13| 0: [LocalVariableAccess] access to local variable o +# 13| 1: [RecursivePatternExpr] { ... } +# 13| 0: [LocalVariableDeclExpr] MyStruct s +# 13| 1: [TypeAccess] access to type MyStruct +# 13| 3: [PropertyPatternExpr] { ... } +# 13| 0: [LabeledPatternExpr,VariablePatternExpr] Int32 x +# 13| 1: [LTExpr] ... < ... +# 13| 0: [LocalVariableAccess] access to local variable x +# 13| 1: [IntLiteral] 4 +# 13| 1: [LTExpr] ... < ... +# 13| 0: [PropertyCall] access to property Y +# 13| -1: [LocalVariableAccess] access to local variable s +# 13| 1: [IntLiteral] 2 +# 14| 1: [BlockStmt] {...} +# 17| 3: [IfStmt] if (...) ... +# 17| 0: [IsExpr] ... is ... +# 17| 0: [LocalVariableAccess] access to local variable o +# 17| 1: [RecursivePatternExpr] { ... } +# 17| 0: [LocalVariableDeclExpr] Object p +# 17| 3: [PropertyPatternExpr] { ... } +# 18| 1: [BlockStmt] {...} +# 22| 4: [IfStmt] if (...) ... +# 22| 0: [IsExpr] ... is ... +# 22| 0: [LocalVariableAccess] access to local variable o +# 22| 1: [RecursivePatternExpr] { ... } +# 22| 1: [TypeAccess] access to type MyStruct +# 22| 3: [PropertyPatternExpr] { ... } +# 22| 0: [ConstantPatternExpr,IntLiteral,LabeledPatternExpr] 12 +# 22| 1: [LabeledPatternExpr,RecursivePatternExpr] { ... } +# 22| 3: [PropertyPatternExpr] { ... } +# 22| 0: [LabeledPatternExpr,VariablePatternExpr] Int32 subX +# 23| 1: [BlockStmt] {...} +# 27| 5: [IfStmt] if (...) ... +# 27| 0: [IsExpr] ... is ... +# 27| 0: [LocalVariableAccess] access to local variable o +# 27| 1: [RecursivePatternExpr] { ... } +# 27| 1: [TypeAccess] access to type MyStruct +# 27| 3: [PropertyPatternExpr] { ... } +# 27| 0: [ConstantPatternExpr,IntLiteral,LabeledPatternExpr] 12 +# 27| 1: [LabeledPatternExpr,RecursivePatternExpr] { ... } +# 27| 0: [LocalVariableDeclExpr] MyStruct ms +# 27| 1: [TypeAccess] access to type MyStruct +# 27| 3: [PropertyPatternExpr] { ... } +# 27| 0: [DiscardPatternExpr,LabeledPatternExpr] _ +# 28| 1: [BlockStmt] {...} +# 32| 6: [Method] SwitchStatements +# 33| 4: [BlockStmt] {...} +# 34| 0: [LocalVariableDeclStmt] ... ...; +# 34| 0: [LocalVariableDeclAndInitExpr] MyStruct s = ... +# 34| 0: [ObjectCreation] object creation of type MyStruct +# 34| -1: [ObjectInitializer] { ..., ... } +# 34| 0: [MemberInitializer] ... = ... +# 34| 0: [IntLiteral] 0 +# 34| 1: [FieldAccess] access to field X +# 34| 1: [LocalVariableAccess] access to local variable s +# 36| 1: [SwitchStmt] switch (...) {...} +# 36| 0: [LocalVariableAccess] access to local variable s +# 38| 0: [CaseStmt] case ...: +# 38| 0: [VariablePatternExpr] MyStruct ms1 +# 38| 1: [EQExpr] ... == ... +# 38| 0: [FieldAccess] access to field X +# 38| -1: [LocalVariableAccess] access to local variable ms1 +# 38| 1: [IntLiteral] 10 +# 39| 1: [ExprStmt] ...; +# 39| 0: [MethodCall] call to method WriteLine +# 39| -1: [TypeAccess] access to type Console +# 39| 0: [StringLiteral] "Hit the breakpoint" +# 40| 2: [BreakStmt] break; +# 41| 3: [CaseStmt] case ...: +# 41| 0: [VariablePatternExpr] MyStruct ms2 +# 41| 1: [LTExpr] ... < ... +# 41| 0: [FieldAccess] access to field X +# 41| -1: [LocalVariableAccess] access to local variable ms2 +# 41| 1: [IntLiteral] 10 +# 42| 4: [ExprStmt] ...; +# 42| 0: [MethodCall] call to method WriteLine +# 42| -1: [TypeAccess] access to type Console +# 42| 0: [StringLiteral] "Missed the breakpoint" +# 43| 5: [BreakStmt] break; +# 46| 2: [SwitchStmt] switch (...) {...} +# 46| 0: [LocalVariableAccess] access to local variable s +# 48| 0: [CaseStmt] case ...: +# 48| 0: [RecursivePatternExpr] { ... } +# 48| 1: [TypeAccess] access to type MyStruct +# 48| 3: [PropertyPatternExpr] { ... } +# 48| 0: [LabeledPatternExpr,VariablePatternExpr] Int32 x +# 48| 1: [GTExpr] ... > ... +# 48| 0: [LocalVariableAccess] access to local variable x +# 48| 1: [IntLiteral] 2 +# 49| 1: [ExprStmt] ...; +# 49| 0: [MethodCall] call to method WriteLine +# 49| -1: [TypeAccess] access to type Console +# 49| 0: [LocalVariableAccess] access to local variable x +# 50| 2: [BreakStmt] break; +# 51| 3: [CaseStmt] case ...: +# 51| 0: [RecursivePatternExpr] { ... } +# 51| 0: [LocalVariableDeclExpr] MyStruct ms +# 51| 1: [TypeAccess] access to type MyStruct +# 51| 3: [PropertyPatternExpr] { ... } +# 51| 0: [ConstantPatternExpr,IntLiteral,LabeledPatternExpr] 10 +# 52| 4: [ExprStmt] ...; +# 52| 0: [MethodCall] call to method WriteLine +# 52| -1: [TypeAccess] access to type Console +# 52| 0: [StringLiteral] "Hit the breakpoint" +# 53| 5: [BreakStmt] break; +# 54| 6: [CaseStmt] case ...: +# 54| 0: [RecursivePatternExpr] { ... } +# 54| 3: [PropertyPatternExpr] { ... } +# 54| 0: [LabeledPatternExpr,VariablePatternExpr] Int32 x2 +# 54| 1: [GTExpr] ... > ... +# 54| 0: [LocalVariableAccess] access to local variable x2 +# 54| 1: [IntLiteral] 2 +# 55| 7: [ExprStmt] ...; +# 55| 0: [MethodCall] call to method WriteLine +# 55| -1: [TypeAccess] access to type Console +# 55| 0: [LocalVariableAccess] access to local variable x2 +# 56| 8: [BreakStmt] break; +# 57| 9: [CaseStmt] case ...: +# 57| 0: [RecursivePatternExpr] { ... } +# 57| 2: [PositionalPatternExpr] ( ... ) +# 57| 0: [ConstantPatternExpr,IntLiteral] 1 +# 57| 1: [ConstantPatternExpr,IntLiteral] 2 +# 58| 10: [BreakStmt] break; +# 59| 11: [CaseStmt] case ...: +# 59| 0: [TupleExpr] (..., ...) +# 59| 0: [LocalVariableDeclExpr] Int32 x +# 59| 1: [LocalVariableDeclExpr] Int32 y +# 60| 12: [BreakStmt] break; +# 61| 13: [DefaultCase] default: +# 62| 14: [BreakStmt] break; +# 65| 3: [SwitchStmt] switch (...) {...} +# 65| 0: [LocalVariableAccess] access to local variable s +# 67| 0: [CaseStmt] case ...: +# 67| 0: [RecursivePatternExpr] { ... } +# 67| 1: [TypeAccess] access to type MyStruct +# 67| 3: [PropertyPatternExpr] { ... } +# 67| 0: [LabeledPatternExpr,VariablePatternExpr] Int32 x +# 67| 1: [GTExpr] ... > ... +# 67| 0: [LocalVariableAccess] access to local variable x +# 67| 1: [IntLiteral] 2 +# 68| 1: [ExprStmt] ...; +# 68| 0: [MethodCall] call to method WriteLine +# 68| -1: [TypeAccess] access to type Console +# 68| 0: [LocalVariableAccess] access to local variable x +# 69| 2: [BreakStmt] break; +# 70| 3: [CaseStmt] case ...: +# 70| 0: [RecursivePatternExpr] { ... } +# 70| 0: [LocalVariableDeclExpr] MyStruct ms +# 70| 1: [TypeAccess] access to type MyStruct +# 70| 3: [PropertyPatternExpr] { ... } +# 70| 0: [ConstantPatternExpr,IntLiteral,LabeledPatternExpr] 10 +# 70| 1: [EQExpr] ... == ... +# 70| 0: [FieldAccess] access to field X +# 70| -1: [LocalVariableAccess] access to local variable s +# 70| 1: [IntLiteral] 0 +# 71| 4: [ExprStmt] ...; +# 71| 0: [MethodCall] call to method WriteLine +# 71| -1: [TypeAccess] access to type Console +# 71| 0: [StringLiteral] "Hit the breakpoint" +# 72| 5: [BreakStmt] break; +# 76| 4: [SwitchStmt] switch (...) {...} +# 76| 0: [ObjectCreation] object creation of type Object +# 78| 0: [CaseStmt] case ...: +# 78| 0: [RecursivePatternExpr] { ... } +# 78| 2: [PositionalPatternExpr] ( ... ) +# 78| 0: [VariablePatternExpr] Int32 x +# 78| 1: [VariablePatternExpr] Single y +# 78| 1: [LTExpr] ... < ... +# 78| 0: [CastExpr] (...) ... +# 78| 0: [LocalVariableAccess] access to local variable x +# 78| 1: [LocalVariableAccess] access to local variable y +# 79| 1: [BreakStmt] break; +# 80| 2: [CaseStmt] case ...: +# 80| 0: [RecursivePatternExpr] { ... } +# 80| 2: [PositionalPatternExpr] ( ... ) +# 81| 3: [BreakStmt] break; +# 82| 4: [CaseStmt] case ...: +# 82| 0: [RecursivePatternExpr] { ... } +# 82| 3: [PropertyPatternExpr] { ... } +# 83| 5: [BreakStmt] break; +# 86| 5: [SwitchStmt] switch (...) {...} +# 86| 0: [TupleExpr] (..., ...) +# 86| 0: [IntLiteral] 1 +# 86| 1: [IntLiteral] 2 +# 88| 0: [CaseStmt] case ...: +# 88| 0: [RecursivePatternExpr] { ... } +# 88| 2: [PositionalPatternExpr] ( ... ) +# 88| 0: [ConstantPatternExpr,IntLiteral] 1 +# 88| 1: [ConstantPatternExpr,IntLiteral] 2 +# 88| 1: [BreakStmt] break; +# 91| 6: [SwitchStmt] switch (...) {...} +# 91| 0: [TupleExpr] (..., ...) +# 91| 0: [IntLiteral] 1 +# 91| 1: [IntLiteral] 2 +# 93| 0: [CaseStmt] case ...: +# 93| 0: [RecursivePatternExpr] { ... } +# 93| 2: [PositionalPatternExpr] ( ... ) +# 93| 0: [ConstantPatternExpr,IntLiteral] 1 +# 93| 1: [VariablePatternExpr] Int32 x +# 93| 1: [BreakStmt] break; +# 94| 2: [CaseStmt] case ...: +# 94| 0: [RecursivePatternExpr] { ... } +# 94| 2: [PositionalPatternExpr] ( ... ) +# 94| 0: [ConstantPatternExpr,IntLiteral] 2 +# 94| 1: [DiscardPatternExpr] _ +# 94| 3: [BreakStmt] break; +# 98| 7: [Method] Expressions +#-----| 2: (Parameters) +# 98| 0: [Parameter] x +# 99| 4: [BlockStmt] {...} +# 100| 0: [LocalVariableDeclStmt] ... ...; +# 100| 0: [LocalVariableDeclAndInitExpr] String size = ... +# 100| 0: [SwitchExpr] ... switch { ... } +# 100| -1: [ParameterAccess] access to parameter x +# 101| 0: [SwitchCaseExpr] ... => ... +# 101| 0: [VariablePatternExpr] Int32 y +# 101| 1: [GTExpr] ... > ... +# 101| 0: [LocalVariableAccess] access to local variable y +# 101| 1: [IntLiteral] 10 +# 101| 2: [StringLiteral] "large" +# 102| 1: [SwitchCaseExpr] ... => ... +# 102| 0: [DiscardPatternExpr] _ +# 102| 2: [StringLiteral] "small" +# 100| 1: [LocalVariableAccess] access to local variable size +# 105| 1: [LocalVariableDeclStmt] ... ...; +# 105| 0: [LocalVariableDeclAndInitExpr] Int32 x0 = ... +# 105| 0: [IntLiteral] 0 +# 105| 1: [LocalVariableAccess] access to local variable x0 +# 105| 1: [LocalVariableDeclAndInitExpr] Int32 y0 = ... +# 105| 0: [IntLiteral] 0 +# 105| 1: [LocalVariableAccess] access to local variable y0 +# 108| 2: [ExprStmt] ...; +# 108| 0: [AssignExpr] ... = ... +# 108| 0: [SwitchExpr] ... switch { ... } +# 108| -1: [TupleExpr] (..., ...) +# 108| 0: [LocalVariableAccess] access to local variable x0 +# 108| 1: [LocalVariableAccess] access to local variable y0 +# 110| 0: [SwitchCaseExpr] ... => ... +# 110| 0: [RecursivePatternExpr] { ... } +# 110| 2: [PositionalPatternExpr] ( ... ) +# 110| 0: [ConstantPatternExpr,IntLiteral] 0 +# 110| 1: [ConstantPatternExpr,IntLiteral] 1 +# 110| 2: [TupleExpr] (..., ...) +# 110| 0: [IntLiteral] 1 +# 110| 1: [IntLiteral] 0 +# 111| 1: [SwitchCaseExpr] ... => ... +# 111| 0: [RecursivePatternExpr] { ... } +# 111| 2: [PositionalPatternExpr] ( ... ) +# 111| 0: [ConstantPatternExpr,IntLiteral] 1 +# 111| 1: [ConstantPatternExpr,IntLiteral] 0 +# 111| 2: [TupleExpr] (..., ...) +# 111| 0: [IntLiteral] 0 +# 111| 1: [IntLiteral] 1 +# 108| 1: [TupleExpr] (..., ...) +# 108| 0: [LocalVariableDeclExpr] Int32 x1 +# 108| 1: [LocalVariableDeclExpr] Int32 y1 +# 115| 3: [ExprStmt] ...; +# 115| 0: [AssignExpr] ... = ... +# 115| 0: [SwitchExpr] ... switch { ... } +# 115| -1: [TupleExpr] (..., ...) +# 115| 0: [LocalVariableAccess] access to local variable x0 +# 115| 1: [LocalVariableAccess] access to local variable y0 +# 117| 0: [SwitchCaseExpr] ... => ... +# 117| 0: [RecursivePatternExpr] { ... } +# 117| 2: [PositionalPatternExpr] ( ... ) +# 117| 0: [ConstantPatternExpr,IntLiteral] 0 +# 117| 1: [VariablePatternExpr] Int32 y2 +# 117| 2: [TupleExpr] (..., ...) +# 117| 0: [LocalVariableAccess] access to local variable y2 +# 117| 1: [IntLiteral] 0 +# 118| 1: [SwitchCaseExpr] ... => ... +# 118| 0: [RecursivePatternExpr] { ... } +# 118| 2: [PositionalPatternExpr] ( ... ) +# 118| 0: [VariablePatternExpr] Int32 x2 +# 118| 1: [ConstantPatternExpr,IntLiteral] 0 +# 118| 2: [TupleExpr] (..., ...) +# 118| 0: [IntLiteral] 0 +# 118| 1: [LocalVariableAccess] access to local variable x2 +# 119| 2: [SwitchCaseExpr] ... => ... +# 119| 0: [RecursivePatternExpr] { ... } +# 119| 2: [PositionalPatternExpr] ( ... ) +# 119| 0: [VariablePatternExpr] Int32 x2 +# 119| 1: [VariablePatternExpr] Int32 y2 +# 119| 2: [TupleExpr] (..., ...) +# 119| 0: [IntLiteral] 0 +# 119| 1: [IntLiteral] 0 +# 115| 1: [TupleExpr] (..., ...) +# 115| 0: [LocalVariableAccess] access to local variable x1 +# 115| 1: [LocalVariableAccess] access to local variable y1 +# 123| 8: [Method] Expressions2 +#-----| 2: (Parameters) +# 123| 0: [Parameter] o +# 124| 4: [BlockStmt] {...} +# 125| 0: [LocalVariableDeclStmt] ... ...; +# 125| 0: [LocalVariableDeclAndInitExpr] MyStruct s = ... +# 125| 0: [ObjectCreation] object creation of type MyStruct +# 125| -1: [ObjectInitializer] { ..., ... } +# 125| 0: [MemberInitializer] ... = ... +# 125| 0: [IntLiteral] 0 +# 125| 1: [FieldAccess] access to field X +# 125| 1: [LocalVariableAccess] access to local variable s +# 126| 1: [LocalVariableDeclStmt] ... ...; +# 126| 0: [LocalVariableDeclAndInitExpr] Int32 r = ... +# 126| 0: [SwitchExpr] ... switch { ... } +# 126| -1: [LocalVariableAccess] access to local variable s +# 128| 0: [SwitchCaseExpr] ... => ... +# 128| 0: [RecursivePatternExpr] { ... } +# 128| 1: [TypeAccess] access to type MyStruct +# 128| 3: [PropertyPatternExpr] { ... } +# 128| 0: [LabeledPatternExpr,VariablePatternExpr] Int32 x +# 128| 1: [GTExpr] ... > ... +# 128| 0: [LocalVariableAccess] access to local variable x +# 128| 1: [IntLiteral] 2 +# 128| 2: [IntLiteral] 0 +# 129| 1: [SwitchCaseExpr] ... => ... +# 129| 0: [RecursivePatternExpr] { ... } +# 129| 0: [LocalVariableDeclExpr] MyStruct ms +# 129| 1: [TypeAccess] access to type MyStruct +# 129| 3: [PropertyPatternExpr] { ... } +# 129| 0: [ConstantPatternExpr,IntLiteral,LabeledPatternExpr] 10 +# 129| 2: [IntLiteral] 1 +# 130| 2: [SwitchCaseExpr] ... => ... +# 130| 0: [RecursivePatternExpr] { ... } +# 130| 2: [PositionalPatternExpr] ( ... ) +# 130| 0: [ConstantPatternExpr,IntLiteral] 1 +# 130| 1: [ConstantPatternExpr,IntLiteral] 2 +# 130| 2: [IntLiteral] 2 +# 131| 3: [SwitchCaseExpr] ... => ... +# 131| 0: [TupleExpr] (..., ...) +# 131| 0: [LocalVariableDeclExpr] Int32 x +# 131| 1: [DiscardExpr] _ +# 131| 2: [IntLiteral] 3 +# 126| 1: [LocalVariableAccess] access to local variable r +# 134| 2: [TryStmt] try {...} ... +# 135| 0: [BlockStmt] {...} +# 136| 0: [ExprStmt] ...; +# 136| 0: [AssignExpr] ... = ... +# 136| 0: [SwitchExpr] ... switch { ... } +# 136| -1: [ParameterAccess] access to parameter o +# 138| 0: [SwitchCaseExpr] ... => ... +# 138| 0: [ConstantPatternExpr,IntLiteral] 1 +# 138| 2: [ThrowExpr] throw ... +# 138| 0: [ObjectCreation] object creation of type ArgumentException +# 139| 1: [SwitchCaseExpr] ... => ... +# 139| 0: [ConstantPatternExpr,IntLiteral] 2 +# 139| 2: [IntLiteral] 3 +# 140| 2: [SwitchCaseExpr] ... => ... +# 140| 0: [VariablePatternExpr] Object y +# 140| 1: [IsExpr] ... is ... +# 140| 0: [LocalVariableAccess] access to local variable y +# 140| 1: [RecursivePatternExpr] { ... } +# 140| 3: [PropertyPatternExpr] { ... } +# 140| 2: [IntLiteral] 4 +# 141| 3: [SwitchCaseExpr] ... => ... +# 141| 0: [TypeAccessPatternExpr] access to type String +# 141| 2: [IntLiteral] 5 +# 142| 4: [SwitchCaseExpr] ... => ... +# 142| 0: [RecursivePatternExpr] { ... } +# 142| 1: [TypeAccess] access to type MyStruct +# 142| 3: [PropertyPatternExpr] { ... } +# 142| 0: [ConstantPatternExpr,IntLiteral,LabeledPatternExpr] 10 +# 142| 2: [IntLiteral] 6 +# 136| 1: [LocalVariableAccess] access to local variable r +# 145| 1: [SpecificCatchClause] catch (...) {...} +# 145| 0: [LocalVariableDeclExpr] InvalidOperationException ex +# 146| 1: [BlockStmt] {...} +# 147| 0: [ExprStmt] ...; +# 147| 0: [MethodCall] call to method WriteLine +# 147| -1: [TypeAccess] access to type Console +# 147| 0: [StringLiteral] "Invalid operation" +# 151| 9: [Struct] MyStruct +# 153| 5: [Field] X +# 154| 6: [Property] Y +# 154| 3: [Getter] get_Y +# 154| 4: [IntLiteral] 10 +# 156| 7: [Property] S +# 156| 3: [Getter] get_S +# 156| 4: [ThisAccess] this access +# 158| 8: [Method] Deconstruct +#-----| 2: (Parameters) +# 158| 0: [Parameter] x +# 158| 1: [Parameter] y +# 159| 4: [BlockStmt] {...} +# 160| 0: [ExprStmt] ...; +# 160| 0: [AssignExpr] ... = ... +# 160| 0: [FieldAccess] access to field X +# 160| 1: [ParameterAccess] access to parameter x +# 161| 1: [ExprStmt] ...; +# 161| 0: [AssignExpr] ... = ... +# 161| 0: [PropertyCall] access to property Y +# 161| 1: [ParameterAccess] access to parameter y +# 164| 9: [Method] Deconstruct +# 165| 4: [BlockStmt] {...} +ranges.cs: +# 25| [NamespaceDeclaration] namespace ... { ... } +# 27| 1: [Struct] Index +# 29| 5: [InstanceConstructor] Index +#-----| 2: (Parameters) +# 29| 0: [Parameter] value +# 29| 1: [Parameter] fromEnd +# 29| 1: [BoolLiteral] false +# 29| 4: [BlockStmt] {...} +# 30| 6: [ImplicitConversionOperator] implicit conversion +#-----| 2: (Parameters) +# 30| 0: [Parameter] value +# 30| 4: [DefaultValueExpr] default(...) +# 30| 0: [TypeAccess] access to type Index +# 33| 2: [Struct] Range +# 35| 5: [InstanceConstructor] Range +#-----| 2: (Parameters) +# 35| 0: [Parameter] start +# 35| 1: [Parameter] end +# 35| 4: [ThrowExpr] throw ... +# 35| 0: [NullLiteral] null +# 36| 6: [Method] StartAt +#-----| 2: (Parameters) +# 36| 0: [Parameter] start +# 36| 4: [ThrowExpr] throw ... +# 36| 0: [NullLiteral] null +# 37| 7: [Method] EndAt +#-----| 2: (Parameters) +# 37| 0: [Parameter] end +# 37| 4: [ThrowExpr] throw ... +# 37| 0: [NullLiteral] null +# 38| 8: [Property] All +# 38| 3: [Getter] get_All +# 38| 4: [ThrowExpr] throw ... +# 38| 0: [NullLiteral] null +# 39| 9: [Method] Create +#-----| 2: (Parameters) +# 39| 0: [Parameter] start +# 39| 1: [Parameter] end +# 39| 4: [ThrowExpr] throw ... +# 39| 0: [NullLiteral] null +# 40| 10: [ImplicitConversionOperator] implicit conversion +#-----| 2: (Parameters) +# 40| 0: [Parameter] r +# 40| 4: [ThrowExpr] throw ... +# 40| 0: [NullLiteral] null +# 5| [Class] Ranges +# 7| 5: [Method] F +# 8| 4: [BlockStmt] {...} +# 9| 0: [LocalVariableDeclStmt] ... ...; +# 9| 0: [LocalVariableDeclAndInitExpr] Int32[] array = ... +# 9| 0: [ArrayCreation] array creation of type Int32[] +# 9| -1: [ArrayInitializer] { ..., ... } +# 9| 0: [IntLiteral] 1 +# 9| 1: [IntLiteral] 2 +# 9| 2: [IntLiteral] 3 +# 9| 3: [IntLiteral] 4 +# 9| 1: [LocalVariableAccess] access to local variable array +# 10| 1: [LocalVariableDeclStmt] ... ...; +# 10| 0: [LocalVariableDeclAndInitExpr] Int32[,] array2 = ... +# 10| 0: [ArrayCreation] array creation of type Int32[,] +# 10| 0: [IntLiteral] 2 +# 10| 1: [IntLiteral] 3 +# 10| 1: [LocalVariableAccess] access to local variable array2 +# 12| 2: [LocalVariableDeclStmt] ... ...; +# 12| 0: [LocalVariableDeclAndInitExpr] Int32 slice1 = ... +# 12| 0: [ArrayAccess] access to array element +# 12| -1: [LocalVariableAccess] access to local variable array +# 12| 0: [OperatorCall] call to operator implicit conversion +# 12| 0: [RangeExpr] ... .. ... +# 12| 0: [OperatorCall] call to operator implicit conversion +# 12| 0: [IntLiteral] 1 +# 12| 1: [OperatorCall] call to operator implicit conversion +# 12| 0: [IntLiteral] 3 +# 12| 1: [LocalVariableAccess] access to local variable slice1 +# 13| 3: [LocalVariableDeclStmt] ... ...; +# 13| 0: [LocalVariableDeclAndInitExpr] Int32 slice2 = ... +# 13| 0: [ArrayAccess] access to array element +# 13| -1: [LocalVariableAccess] access to local variable array +# 13| 0: [OperatorCall] call to operator implicit conversion +# 13| 0: [RangeExpr] ... .. ... +# 13| 0: [OperatorCall] call to operator implicit conversion +# 13| 0: [IntLiteral] 0 +# 13| 1: [IndexExpr] ^... +# 13| 0: [IntLiteral] 1 +# 13| 1: [LocalVariableAccess] access to local variable slice2 +# 14| 4: [LocalVariableDeclStmt] ... ...; +# 14| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 14| 0: [IntLiteral] 2 +# 14| 1: [LocalVariableAccess] access to local variable x +# 14| 1: [LocalVariableDeclAndInitExpr] Int32 y = ... +# 14| 0: [IntLiteral] 3 +# 14| 1: [LocalVariableAccess] access to local variable y +# 15| 5: [LocalVariableDeclStmt] ... ...; +# 15| 0: [LocalVariableDeclAndInitExpr] Int32 slice3 = ... +# 15| 0: [ArrayAccess] access to array element +# 15| -1: [LocalVariableAccess] access to local variable array +# 15| 0: [OperatorCall] call to operator implicit conversion +# 15| 0: [RangeExpr] ... .. ... +# 15| 0: [OperatorCall] call to operator implicit conversion +# 15| 0: [LocalVariableAccess] access to local variable x +# 15| 1: [OperatorCall] call to operator implicit conversion +# 15| 0: [LocalVariableAccess] access to local variable y +# 15| 1: [LocalVariableAccess] access to local variable slice3 +# 16| 6: [LocalVariableDeclStmt] ... ...; +# 16| 0: [LocalVariableDeclAndInitExpr] Int32 slice4 = ... +# 16| 0: [ArrayAccess] access to array element +# 16| -1: [LocalVariableAccess] access to local variable array +# 16| 0: [OperatorCall] call to operator implicit conversion +# 16| 0: [RangeExpr] ... .. ... +# 16| 1: [OperatorCall] call to operator implicit conversion +# 16| 0: [LocalVariableAccess] access to local variable y +# 16| 1: [LocalVariableAccess] access to local variable slice4 +# 17| 7: [LocalVariableDeclStmt] ... ...; +# 17| 0: [LocalVariableDeclAndInitExpr] Int32 slice5 = ... +# 17| 0: [ArrayAccess] access to array element +# 17| -1: [LocalVariableAccess] access to local variable array +# 17| 0: [OperatorCall] call to operator implicit conversion +# 17| 0: [RangeExpr] ... .. ... +# 17| 0: [OperatorCall] call to operator implicit conversion +# 17| 0: [LocalVariableAccess] access to local variable x +# 17| 1: [LocalVariableAccess] access to local variable slice5 +# 18| 8: [LocalVariableDeclStmt] ... ...; +# 18| 0: [LocalVariableDeclAndInitExpr] Int32 slice6 = ... +# 18| 0: [ArrayAccess] access to array element +# 18| -1: [LocalVariableAccess] access to local variable array +# 18| 0: [OperatorCall] call to operator implicit conversion +# 18| 0: [RangeExpr] ... .. ... +# 18| 1: [LocalVariableAccess] access to local variable slice6 +# 19| 9: [LocalVariableDeclStmt] ... ...; +# 19| 0: [LocalVariableDeclAndInitExpr] Int32 slice7 = ... +# 19| 0: [ArrayAccess] access to array element +# 19| -1: [LocalVariableAccess] access to local variable array +# 19| 0: [OperatorCall] call to operator implicit conversion +# 19| 0: [RangeExpr] ... .. ... +# 19| 0: [IndexExpr] ^... +# 19| 0: [IntLiteral] 10 +# 19| 1: [IndexExpr] ^... +# 19| 0: [IntLiteral] 5 +# 19| 1: [LocalVariableAccess] access to local variable slice7 +# 20| 10: [LocalVariableDeclStmt] ... ...; +# 20| 0: [LocalVariableDeclAndInitExpr] Int32 slice8 = ... +# 20| 0: [ArrayAccess] access to array element +# 20| -1: [LocalVariableAccess] access to local variable array2 +# 20| 0: [OperatorCall] call to operator implicit conversion +# 20| 0: [RangeExpr] ... .. ... +# 20| 0: [OperatorCall] call to operator implicit conversion +# 20| 0: [IntLiteral] 1 +# 20| 1: [OperatorCall] call to operator implicit conversion +# 20| 0: [IntLiteral] 2 +# 20| 1: [OperatorCall] call to operator implicit conversion +# 20| 0: [RangeExpr] ... .. ... +# 20| 1: [LocalVariableAccess] access to local variable slice8 diff --git a/csharp/ql/test/library-tests/csharp8/PrintAst.qlref b/csharp/ql/test/library-tests/csharp8/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/csharp8/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/definitions/PrintAst.expected b/csharp/ql/test/library-tests/definitions/PrintAst.expected new file mode 100644 index 00000000000..825519a280d --- /dev/null +++ b/csharp/ql/test/library-tests/definitions/PrintAst.expected @@ -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 nullable = ... +# 64| 0: [NullLiteral] null +# 64| 1: [LocalVariableAccess] access to local variable nullable +# 67| 20: [LocalVariableDeclStmt] ... ...; +# 67| 0: [LocalVariableDeclAndInitExpr] Action m1 = ... +# 67| 0: [ImplicitDelegateCreation] delegate creation of type Action +# 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 +# 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 +# 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 +# 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 +# 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 +# 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; diff --git a/csharp/ql/test/library-tests/definitions/PrintAst.qlref b/csharp/ql/test/library-tests/definitions/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/definitions/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/delegates/PrintAst.expected b/csharp/ql/test/library-tests/delegates/PrintAst.expected new file mode 100644 index 00000000000..0c73aa05ae1 --- /dev/null +++ b/csharp/ql/test/library-tests/delegates/PrintAst.expected @@ -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 pi = ... +# 76| 0: [ExplicitDelegateCreation] delegate creation of type Predicate +# 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 ps = ... +# 77| 0: [ImplicitDelegateCreation] delegate creation of type Predicate +# 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 diff --git a/csharp/ql/test/library-tests/delegates/PrintAst.qlref b/csharp/ql/test/library-tests/delegates/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/delegates/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dynamic/PrintAst.expected b/csharp/ql/test/library-tests/dynamic/PrintAst.expected new file mode 100644 index 00000000000..adaec26beb3 --- /dev/null +++ b/csharp/ql/test/library-tests/dynamic/PrintAst.expected @@ -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 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 +# 18| 0: [StringLiteral] "" +# 18| 1: [LocalVariableAccess] access to local variable d +# 19| 7: [ExprStmt] ...; +# 19| 0: [DynamicObjectCreation] dynamic object creation of type KeyValuePair +# 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] {...} diff --git a/csharp/ql/test/library-tests/dynamic/PrintAst.qlref b/csharp/ql/test/library-tests/dynamic/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/dynamic/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/enums/PrintAst.expected b/csharp/ql/test/library-tests/enums/PrintAst.expected new file mode 100644 index 00000000000..05101b6ca19 --- /dev/null +++ b/csharp/ql/test/library-tests/enums/PrintAst.expected @@ -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" diff --git a/csharp/ql/test/library-tests/enums/PrintAst.qlref b/csharp/ql/test/library-tests/enums/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/enums/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/events/PrintAst.expected b/csharp/ql/test/library-tests/events/PrintAst.expected new file mode 100644 index 00000000000..0e6b3235e59 --- /dev/null +++ b/csharp/ql/test/library-tests/events/PrintAst.expected @@ -0,0 +1,149 @@ +events.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 7| 1: [DelegateType] EventHandler +#-----| 2: (Parameters) +# 7| 0: [Parameter] sender +# 7| 1: [Parameter] e +# 10| 2: [Class] Button +# 13| 5: [Event] Click +# 13| 3: [RemoveEventAccessor] remove_Click +#-----| 2: (Parameters) +# 13| 0: [Parameter] value +# 13| 3: [AddEventAccessor] add_Click +#-----| 2: (Parameters) +# 13| 0: [Parameter] value +# 15| 6: [Method] OnClick +#-----| 2: (Parameters) +# 15| 0: [Parameter] e +# 16| 4: [BlockStmt] {...} +# 17| 0: [IfStmt] if (...) ... +# 17| 0: [OperatorCall] call to operator != +# 17| 0: [EventAccess,EventCall] access to event Click +# 17| 1: [NullLiteral] null +# 18| 1: [ExprStmt] ...; +# 18| 0: [DelegateCall] delegate call +# 18| -1: [EventAccess,EventCall] access to event Click +# 18| 0: [ThisAccess] this access +# 18| 1: [ParameterAccess] access to parameter e +# 21| 7: [Method] Reset +# 22| 4: [BlockStmt] {...} +# 23| 0: [ExprStmt] ...; +# 23| 0: [AssignExpr] ... = ... +# 23| 0: [NullLiteral] null +# 23| 1: [EventAccess,EventCall] access to event Click +# 27| 3: [Class] LoginDialog +# 30| 4: [Field] OkButton +# 31| 5: [Field] CancelButton +# 33| 6: [InstanceConstructor] LoginDialog +# 34| 4: [BlockStmt] {...} +# 35| 0: [ExprStmt] ...; +# 35| 0: [AssignExpr] ... = ... +# 35| 0: [ObjectCreation] object creation of type Button +# 35| 1: [FieldAccess] access to field OkButton +# 36| 1: [ExprStmt] ...; +# 36| 0: [AddEventExpr] ... += ... +# 36| 0: [ExplicitDelegateCreation] delegate creation of type EventHandler +# 36| 0: [MethodAccess] access to method OkButtonClick +# 36| 1: [EventAccess,EventCall] access to event Click +# 36| -1: [FieldAccess] access to field OkButton +# 37| 2: [ExprStmt] ...; +# 37| 0: [AssignExpr] ... = ... +# 37| 0: [ObjectCreation] object creation of type Button +# 37| 1: [FieldAccess] access to field CancelButton +# 38| 3: [ExprStmt] ...; +# 38| 0: [RemoveEventExpr] ... -= ... +# 38| 0: [ExplicitDelegateCreation] delegate creation of type EventHandler +# 38| 0: [MethodAccess] access to method CancelButtonClick +# 38| 1: [EventAccess,EventCall] access to event Click +# 38| -1: [FieldAccess] access to field CancelButton +# 41| 7: [Method] OkButtonClick +#-----| 2: (Parameters) +# 41| 0: [Parameter] sender +# 41| 1: [Parameter] e +# 42| 4: [BlockStmt] {...} +# 45| 8: [Method] CancelButtonClick +#-----| 2: (Parameters) +# 45| 0: [Parameter] sender +# 45| 1: [Parameter] e +# 46| 4: [BlockStmt] {...} +# 51| 4: [Class] Control +# 54| 6: [Field] mouseDownEventKey +# 54| 1: [AssignExpr] ... = ... +# 54| 0: [ObjectCreation] object creation of type Object +# 54| 1: [FieldAccess] access to field mouseDownEventKey +# 55| 7: [Field] mouseUpEventKey +# 55| 1: [AssignExpr] ... = ... +# 55| 0: [ObjectCreation] object creation of type Object +# 55| 1: [FieldAccess] access to field mouseUpEventKey +# 58| 8: [Method] GetEventHandler +#-----| 2: (Parameters) +# 58| 0: [Parameter] key +# 58| 4: [BlockStmt] {...} +# 58| 0: [ReturnStmt] return ...; +# 58| 0: [NullLiteral] null +# 61| 9: [Method] AddEventHandler +#-----| 2: (Parameters) +# 61| 0: [Parameter] key +# 61| 1: [Parameter] handler +# 61| 4: [BlockStmt] {...} +# 64| 10: [Method] RemoveEventHandler +#-----| 2: (Parameters) +# 64| 0: [Parameter] key +# 64| 1: [Parameter] handler +# 64| 4: [BlockStmt] {...} +# 67| 11: [Event] MouseDown +# 69| 3: [AddEventAccessor] add_MouseDown +#-----| 2: (Parameters) +# 69| 0: [Parameter] value +# 69| 4: [BlockStmt] {...} +# 69| 0: [ExprStmt] ...; +# 69| 0: [MethodCall] call to method AddEventHandler +# 69| 0: [FieldAccess] access to field mouseDownEventKey +# 69| 1: [ParameterAccess] access to parameter value +# 70| 4: [RemoveEventAccessor] remove_MouseDown +#-----| 2: (Parameters) +# 70| 0: [Parameter] value +# 70| 4: [BlockStmt] {...} +# 70| 0: [ExprStmt] ...; +# 70| 0: [MethodCall] call to method RemoveEventHandler +# 70| 0: [FieldAccess] access to field mouseDownEventKey +# 70| 1: [ParameterAccess] access to parameter value +# 74| 12: [Event] MouseUp +# 76| 3: [AddEventAccessor] add_MouseUp +#-----| 2: (Parameters) +# 76| 0: [Parameter] value +# 76| 4: [BlockStmt] {...} +# 76| 0: [ExprStmt] ...; +# 76| 0: [MethodCall] call to method AddEventHandler +# 76| 0: [FieldAccess] access to field mouseUpEventKey +# 76| 1: [ParameterAccess] access to parameter value +# 77| 4: [RemoveEventAccessor] remove_MouseUp +#-----| 2: (Parameters) +# 77| 0: [Parameter] value +# 77| 4: [BlockStmt] {...} +# 77| 0: [ExprStmt] ...; +# 77| 0: [MethodCall] call to method RemoveEventHandler +# 77| 0: [FieldAccess] access to field mouseUpEventKey +# 77| 1: [ParameterAccess] access to parameter value +# 81| 13: [Method] OnMouseUp +#-----| 2: (Parameters) +# 81| 0: [Parameter] args +# 82| 4: [BlockStmt] {...} +# 83| 0: [LocalVariableDeclStmt] ... ...; +# 83| 0: [LocalVariableDeclExpr] EventHandler handler +# 84| 1: [ExprStmt] ...; +# 84| 0: [AssignExpr] ... = ... +# 84| 0: [CastExpr] (...) ... +# 84| 0: [MethodCall] call to method GetEventHandler +# 84| 0: [FieldAccess] access to field mouseUpEventKey +# 84| 1: [TypeAccess] access to type EventHandler +# 84| 1: [LocalVariableAccess] access to local variable handler +# 85| 2: [IfStmt] if (...) ... +# 85| 0: [OperatorCall] call to operator != +# 85| 0: [LocalVariableAccess] access to local variable handler +# 85| 1: [NullLiteral] null +# 86| 1: [ExprStmt] ...; +# 86| 0: [DelegateCall] delegate call +# 86| -1: [LocalVariableAccess] access to local variable handler +# 86| 0: [ThisAccess] this access +# 86| 1: [ParameterAccess] access to parameter args diff --git a/csharp/ql/test/library-tests/events/PrintAst.qlref b/csharp/ql/test/library-tests/events/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/events/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/exceptions/PrintAst.expected b/csharp/ql/test/library-tests/exceptions/PrintAst.expected new file mode 100644 index 00000000000..abcca7b9d3a --- /dev/null +++ b/csharp/ql/test/library-tests/exceptions/PrintAst.expected @@ -0,0 +1,503 @@ +exceptions.cs: +# 3| [Class] Class1 +# 5| 5: [Method] G +# 6| 4: [BlockStmt] {...} +# 9| 6: [Field] p +# 11| 7: [Method] TestNoThrow +# 12| 4: [BlockStmt] {...} +# 13| 0: [TryStmt] try {...} ... +# 38| -1: [BlockStmt] {...} +# 39| 0: [EmptyStmt] ; +# 14| 0: [BlockStmt] {...} +# 15| 0: [EmptyStmt] ; +# 17| 1: [SpecificCatchClause] catch (...) {...} +# 17| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 18| 1: [BlockStmt] {...} +# 19| 0: [EmptyStmt] ; +# 21| 2: [SpecificCatchClause] catch (...) {...} +# 21| 0: [LocalVariableDeclExpr] OverflowException ex +# 22| 1: [BlockStmt] {...} +# 23| 0: [EmptyStmt] ; +# 25| 3: [SpecificCatchClause] catch (...) {...} +# 25| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 26| 1: [BlockStmt] {...} +# 27| 0: [EmptyStmt] ; +# 29| 4: [SpecificCatchClause] catch (...) {...} +# 29| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 30| 1: [BlockStmt] {...} +# 31| 0: [EmptyStmt] ; +# 33| 5: [SpecificCatchClause] catch (...) {...} +# 33| 0: [LocalVariableDeclExpr] Exception ex +# 34| 1: [BlockStmt] {...} +# 35| 0: [EmptyStmt] ; +# 43| 8: [Method] TestCall +# 44| 4: [BlockStmt] {...} +# 45| 0: [TryStmt] try {...} ... +# 46| 0: [BlockStmt] {...} +# 47| 0: [EmptyStmt] ; +# 48| 1: [ExprStmt] ...; +# 48| 0: [MethodCall] call to method G +# 50| 1: [SpecificCatchClause] catch (...) {...} +# 50| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 51| 1: [BlockStmt] {...} +# 52| 0: [EmptyStmt] ; +# 54| 2: [SpecificCatchClause] catch (...) {...} +# 54| 0: [LocalVariableDeclExpr] OverflowException ex +# 55| 1: [BlockStmt] {...} +# 56| 0: [EmptyStmt] ; +# 58| 3: [SpecificCatchClause] catch (...) {...} +# 58| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 59| 1: [BlockStmt] {...} +# 60| 0: [EmptyStmt] ; +# 62| 4: [SpecificCatchClause] catch (...) {...} +# 62| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 63| 1: [BlockStmt] {...} +# 64| 0: [EmptyStmt] ; +# 66| 5: [GeneralCatchClause] catch {...} +# 67| 1: [BlockStmt] {...} +# 68| 0: [EmptyStmt] ; +# 72| 9: [Method] TestCreation +# 73| 4: [BlockStmt] {...} +# 74| 0: [TryStmt] try {...} ... +# 75| 0: [BlockStmt] {...} +# 76| 0: [EmptyStmt] ; +# 77| 1: [LocalVariableDeclStmt] ... ...; +# 77| 0: [LocalVariableDeclAndInitExpr] Class1 v = ... +# 77| 0: [ObjectCreation] object creation of type Class1 +# 77| 1: [LocalVariableAccess] access to local variable v +# 79| 1: [SpecificCatchClause] catch (...) {...} +# 79| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 80| 1: [BlockStmt] {...} +# 81| 0: [EmptyStmt] ; +# 83| 2: [SpecificCatchClause] catch (...) {...} +# 83| 0: [LocalVariableDeclExpr] OverflowException ex +# 84| 1: [BlockStmt] {...} +# 85| 0: [EmptyStmt] ; +# 87| 3: [SpecificCatchClause] catch (...) {...} +# 87| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 88| 1: [BlockStmt] {...} +# 89| 0: [EmptyStmt] ; +# 91| 4: [SpecificCatchClause] catch (...) {...} +# 91| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 92| 1: [BlockStmt] {...} +# 93| 0: [EmptyStmt] ; +# 95| 5: [SpecificCatchClause] catch (...) {...} +# 95| 0: [LocalVariableDeclExpr] Exception ex +# 96| 1: [BlockStmt] {...} +# 97| 0: [EmptyStmt] ; +# 101| 10: [Method] TestIntAdd +# 102| 4: [BlockStmt] {...} +# 103| 0: [TryStmt] try {...} ... +# 104| 0: [BlockStmt] {...} +# 105| 0: [EmptyStmt] ; +# 106| 1: [LocalVariableDeclStmt] ... ...; +# 106| 0: [LocalVariableDeclAndInitExpr] Int32 v = ... +# 106| 0: [AddExpr] ... + ... +# 106| 0: [IntLiteral] 1 +# 106| 1: [IntLiteral] 2 +# 106| 1: [LocalVariableAccess] access to local variable v +# 108| 1: [SpecificCatchClause] catch (...) {...} +# 108| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 109| 1: [BlockStmt] {...} +# 110| 0: [EmptyStmt] ; +# 112| 2: [SpecificCatchClause] catch (...) {...} +# 112| 0: [LocalVariableDeclExpr] OverflowException ex +# 113| 1: [BlockStmt] {...} +# 114| 0: [EmptyStmt] ; +# 116| 3: [SpecificCatchClause] catch (...) {...} +# 116| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 117| 1: [BlockStmt] {...} +# 118| 0: [EmptyStmt] ; +# 120| 4: [SpecificCatchClause] catch (...) {...} +# 120| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 121| 1: [BlockStmt] {...} +# 122| 0: [EmptyStmt] ; +# 124| 5: [SpecificCatchClause] catch (...) {...} +# 124| 0: [LocalVariableDeclExpr] Exception ex +# 125| 1: [BlockStmt] {...} +# 126| 0: [EmptyStmt] ; +# 130| 11: [Method] TestIntSub +# 131| 4: [BlockStmt] {...} +# 132| 0: [TryStmt] try {...} ... +# 133| 0: [BlockStmt] {...} +# 134| 0: [EmptyStmt] ; +# 135| 1: [LocalVariableDeclStmt] ... ...; +# 135| 0: [LocalVariableDeclAndInitExpr] Int32 v = ... +# 135| 0: [SubExpr] ... - ... +# 135| 0: [IntLiteral] 1 +# 135| 1: [IntLiteral] 2 +# 135| 1: [LocalVariableAccess] access to local variable v +# 137| 1: [SpecificCatchClause] catch (...) {...} +# 137| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 138| 1: [BlockStmt] {...} +# 139| 0: [EmptyStmt] ; +# 141| 2: [SpecificCatchClause] catch (...) {...} +# 141| 0: [LocalVariableDeclExpr] OverflowException ex +# 142| 1: [BlockStmt] {...} +# 143| 0: [EmptyStmt] ; +# 145| 3: [SpecificCatchClause] catch (...) {...} +# 145| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 146| 1: [BlockStmt] {...} +# 147| 0: [EmptyStmt] ; +# 149| 4: [SpecificCatchClause] catch (...) {...} +# 149| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 150| 1: [BlockStmt] {...} +# 151| 0: [EmptyStmt] ; +# 153| 5: [SpecificCatchClause] catch (...) {...} +# 153| 0: [LocalVariableDeclExpr] Exception ex +# 154| 1: [BlockStmt] {...} +# 155| 0: [EmptyStmt] ; +# 159| 12: [Method] TestIntMul +# 160| 4: [BlockStmt] {...} +# 161| 0: [TryStmt] try {...} ... +# 162| 0: [BlockStmt] {...} +# 163| 0: [EmptyStmt] ; +# 164| 1: [LocalVariableDeclStmt] ... ...; +# 164| 0: [LocalVariableDeclAndInitExpr] Int32 v = ... +# 164| 0: [MulExpr] ... * ... +# 164| 0: [IntLiteral] 1 +# 164| 1: [IntLiteral] 2 +# 164| 1: [LocalVariableAccess] access to local variable v +# 166| 1: [SpecificCatchClause] catch (...) {...} +# 166| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 167| 1: [BlockStmt] {...} +# 168| 0: [EmptyStmt] ; +# 170| 2: [SpecificCatchClause] catch (...) {...} +# 170| 0: [LocalVariableDeclExpr] OverflowException ex +# 171| 1: [BlockStmt] {...} +# 172| 0: [EmptyStmt] ; +# 174| 3: [SpecificCatchClause] catch (...) {...} +# 174| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 175| 1: [BlockStmt] {...} +# 176| 0: [EmptyStmt] ; +# 178| 4: [SpecificCatchClause] catch (...) {...} +# 178| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 179| 1: [BlockStmt] {...} +# 180| 0: [EmptyStmt] ; +# 182| 5: [SpecificCatchClause] catch (...) {...} +# 182| 0: [LocalVariableDeclExpr] Exception ex +# 183| 1: [BlockStmt] {...} +# 184| 0: [EmptyStmt] ; +# 188| 13: [Method] TestStringLiteral +# 189| 4: [BlockStmt] {...} +# 190| 0: [TryStmt] try {...} ... +# 191| 0: [BlockStmt] {...} +# 192| 0: [EmptyStmt] ; +# 193| 1: [LocalVariableDeclStmt] ... ...; +# 193| 0: [LocalVariableDeclAndInitExpr] String v = ... +# 193| 0: [StringLiteral] "" +# 193| 1: [LocalVariableAccess] access to local variable v +# 195| 1: [SpecificCatchClause] catch (...) {...} +# 195| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 196| 1: [BlockStmt] {...} +# 197| 0: [EmptyStmt] ; +# 199| 2: [SpecificCatchClause] catch (...) {...} +# 199| 0: [LocalVariableDeclExpr] OverflowException ex +# 200| 1: [BlockStmt] {...} +# 201| 0: [EmptyStmt] ; +# 203| 3: [SpecificCatchClause] catch (...) {...} +# 203| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 204| 1: [BlockStmt] {...} +# 205| 0: [EmptyStmt] ; +# 207| 4: [SpecificCatchClause] catch (...) {...} +# 207| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 208| 1: [BlockStmt] {...} +# 209| 0: [EmptyStmt] ; +# 211| 5: [SpecificCatchClause] catch (...) {...} +# 211| 0: [LocalVariableDeclExpr] Exception ex +# 212| 1: [BlockStmt] {...} +# 213| 0: [EmptyStmt] ; +# 217| 14: [Method] TestStringAdd +# 218| 4: [BlockStmt] {...} +# 219| 0: [TryStmt] try {...} ... +# 220| 0: [BlockStmt] {...} +# 221| 0: [LocalVariableDeclStmt] ... ...; +# 221| 0: [LocalVariableDeclAndInitExpr] String s = ... +# 221| 0: [StringLiteral] "" +# 221| 1: [LocalVariableAccess] access to local variable s +# 222| 1: [EmptyStmt] ; +# 223| 2: [LocalVariableDeclStmt] ... ...; +# 223| 0: [LocalVariableDeclAndInitExpr] String v = ... +# 223| 0: [AddExpr] ... + ... +# 223| 0: [LocalVariableAccess] access to local variable s +# 223| 1: [LocalVariableAccess] access to local variable s +# 223| 1: [LocalVariableAccess] access to local variable v +# 225| 1: [SpecificCatchClause] catch (...) {...} +# 225| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 226| 1: [BlockStmt] {...} +# 227| 0: [EmptyStmt] ; +# 229| 2: [SpecificCatchClause] catch (...) {...} +# 229| 0: [LocalVariableDeclExpr] OverflowException ex +# 230| 1: [BlockStmt] {...} +# 231| 0: [EmptyStmt] ; +# 233| 3: [SpecificCatchClause] catch (...) {...} +# 233| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 234| 1: [BlockStmt] {...} +# 235| 0: [EmptyStmt] ; +# 237| 4: [SpecificCatchClause] catch (...) {...} +# 237| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 238| 1: [BlockStmt] {...} +# 239| 0: [EmptyStmt] ; +# 241| 5: [SpecificCatchClause] catch (...) {...} +# 241| 0: [LocalVariableDeclExpr] Exception ex +# 242| 1: [BlockStmt] {...} +# 243| 0: [EmptyStmt] ; +# 247| 15: [Method] TestDivide +# 248| 4: [BlockStmt] {...} +# 249| 0: [TryStmt] try {...} ... +# 250| 0: [BlockStmt] {...} +# 251| 0: [EmptyStmt] ; +# 252| 1: [LocalVariableDeclStmt] ... ...; +# 252| 0: [LocalVariableDeclAndInitExpr] Int32 v = ... +# 252| 0: [DivExpr] ... / ... +# 252| 0: [IntLiteral] 1 +# 252| 1: [IntLiteral] 2 +# 252| 1: [LocalVariableAccess] access to local variable v +# 254| 1: [SpecificCatchClause] catch (...) {...} +# 254| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 255| 1: [BlockStmt] {...} +# 256| 0: [EmptyStmt] ; +# 258| 2: [SpecificCatchClause] catch (...) {...} +# 258| 0: [LocalVariableDeclExpr] OverflowException ex +# 259| 1: [BlockStmt] {...} +# 260| 0: [EmptyStmt] ; +# 262| 3: [SpecificCatchClause] catch (...) {...} +# 262| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 263| 1: [BlockStmt] {...} +# 264| 0: [EmptyStmt] ; +# 266| 4: [SpecificCatchClause] catch (...) {...} +# 266| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 267| 1: [BlockStmt] {...} +# 268| 0: [EmptyStmt] ; +# 270| 5: [SpecificCatchClause] catch (...) {...} +# 270| 0: [LocalVariableDeclExpr] Exception ex +# 271| 1: [BlockStmt] {...} +# 272| 0: [EmptyStmt] ; +# 276| 16: [Method] TestRemainder +# 277| 4: [BlockStmt] {...} +# 278| 0: [TryStmt] try {...} ... +# 279| 0: [BlockStmt] {...} +# 280| 0: [EmptyStmt] ; +# 281| 1: [LocalVariableDeclStmt] ... ...; +# 281| 0: [LocalVariableDeclAndInitExpr] Int32 v = ... +# 281| 0: [RemExpr] ... % ... +# 281| 0: [IntLiteral] 1 +# 281| 1: [IntLiteral] 2 +# 281| 1: [LocalVariableAccess] access to local variable v +# 283| 1: [SpecificCatchClause] catch (...) {...} +# 283| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 284| 1: [BlockStmt] {...} +# 285| 0: [EmptyStmt] ; +# 287| 2: [SpecificCatchClause] catch (...) {...} +# 287| 0: [LocalVariableDeclExpr] OverflowException ex +# 288| 1: [BlockStmt] {...} +# 289| 0: [EmptyStmt] ; +# 291| 3: [SpecificCatchClause] catch (...) {...} +# 291| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 292| 1: [BlockStmt] {...} +# 293| 0: [EmptyStmt] ; +# 295| 4: [SpecificCatchClause] catch (...) {...} +# 295| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 296| 1: [BlockStmt] {...} +# 297| 0: [EmptyStmt] ; +# 299| 5: [SpecificCatchClause] catch (...) {...} +# 299| 0: [LocalVariableDeclExpr] Exception ex +# 300| 1: [BlockStmt] {...} +# 301| 0: [EmptyStmt] ; +# 305| 17: [Method] TestMemberAccess +# 306| 4: [BlockStmt] {...} +# 307| 0: [TryStmt] try {...} ... +# 308| 0: [BlockStmt] {...} +# 309| 0: [EmptyStmt] ; +# 310| 1: [LocalVariableDeclStmt] ... ...; +# 310| 0: [LocalVariableDeclAndInitExpr] Int32 v = ... +# 310| 0: [FieldAccess] access to field p +# 310| -1: [ThisAccess] this access +# 310| 1: [LocalVariableAccess] access to local variable v +# 312| 1: [SpecificCatchClause] catch (...) {...} +# 312| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 313| 1: [BlockStmt] {...} +# 314| 0: [EmptyStmt] ; +# 316| 2: [SpecificCatchClause] catch (...) {...} +# 316| 0: [LocalVariableDeclExpr] OverflowException ex +# 317| 1: [BlockStmt] {...} +# 318| 0: [EmptyStmt] ; +# 320| 3: [SpecificCatchClause] catch (...) {...} +# 320| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 321| 1: [BlockStmt] {...} +# 322| 0: [EmptyStmt] ; +# 324| 4: [SpecificCatchClause] catch (...) {...} +# 324| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 325| 1: [BlockStmt] {...} +# 326| 0: [EmptyStmt] ; +# 328| 5: [SpecificCatchClause] catch (...) {...} +# 328| 0: [LocalVariableDeclExpr] Exception ex +# 329| 1: [BlockStmt] {...} +# 330| 0: [EmptyStmt] ; +# 334| 18: [Method] TestCast +# 335| 4: [BlockStmt] {...} +# 336| 0: [TryStmt] try {...} ... +# 337| 0: [BlockStmt] {...} +# 338| 0: [EmptyStmt] ; +# 339| 1: [LocalVariableDeclStmt] ... ...; +# 339| 0: [LocalVariableDeclAndInitExpr] Int16 v = ... +# 339| 0: [CastExpr] (...) ... +# 339| 0: [IntLiteral] 1 +# 339| 1: [TypeAccess] access to type Int16 +# 339| 1: [LocalVariableAccess] access to local variable v +# 341| 1: [SpecificCatchClause] catch (...) {...} +# 341| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 342| 1: [BlockStmt] {...} +# 343| 0: [EmptyStmt] ; +# 345| 2: [SpecificCatchClause] catch (...) {...} +# 345| 0: [LocalVariableDeclExpr] OverflowException ex +# 346| 1: [BlockStmt] {...} +# 347| 0: [EmptyStmt] ; +# 349| 3: [SpecificCatchClause] catch (...) {...} +# 349| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 350| 1: [BlockStmt] {...} +# 351| 0: [EmptyStmt] ; +# 353| 4: [SpecificCatchClause] catch (...) {...} +# 353| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 354| 1: [BlockStmt] {...} +# 355| 0: [EmptyStmt] ; +# 357| 5: [SpecificCatchClause] catch (...) {...} +# 357| 0: [LocalVariableDeclExpr] Exception ex +# 358| 1: [BlockStmt] {...} +# 359| 0: [EmptyStmt] ; +# 363| 19: [Method] TestThrow +# 364| 4: [BlockStmt] {...} +# 365| 0: [TryStmt] try {...} ... +# 366| 0: [BlockStmt] {...} +# 367| 0: [LocalVariableDeclStmt] ... ...; +# 367| 0: [LocalVariableDeclAndInitExpr] DivideByZeroException e = ... +# 367| 0: [ObjectCreation] object creation of type DivideByZeroException +# 367| 1: [LocalVariableAccess] access to local variable e +# 368| 1: [EmptyStmt] ; +# 369| 2: [ThrowStmt] throw ...; +# 369| 0: [LocalVariableAccess] access to local variable e +# 371| 1: [SpecificCatchClause] catch (...) {...} +# 371| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 372| 1: [BlockStmt] {...} +# 373| 0: [EmptyStmt] ; +# 375| 2: [SpecificCatchClause] catch (...) {...} +# 375| 0: [LocalVariableDeclExpr] OverflowException ex +# 376| 1: [BlockStmt] {...} +# 377| 0: [EmptyStmt] ; +# 379| 3: [SpecificCatchClause] catch (...) {...} +# 379| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 380| 1: [BlockStmt] {...} +# 381| 0: [EmptyStmt] ; +# 383| 4: [SpecificCatchClause] catch (...) {...} +# 383| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 384| 1: [BlockStmt] {...} +# 385| 0: [EmptyStmt] ; +# 387| 5: [SpecificCatchClause] catch (...) {...} +# 387| 0: [LocalVariableDeclExpr] Exception ex +# 388| 1: [BlockStmt] {...} +# 389| 0: [EmptyStmt] ; +# 393| 20: [Method] TestUnaryOperation +# 394| 4: [BlockStmt] {...} +# 395| 0: [TryStmt] try {...} ... +# 396| 0: [BlockStmt] {...} +# 397| 0: [LocalVariableDeclStmt] ... ...; +# 397| 0: [LocalVariableDeclAndInitExpr] Int32 a = ... +# 397| 0: [IntLiteral] 1 +# 397| 1: [LocalVariableAccess] access to local variable a +# 398| 1: [EmptyStmt] ; +# 399| 2: [ExprStmt] ...; +# 399| 0: [PreIncrExpr] ++... +# 399| 0: [LocalVariableAccess] access to local variable a +# 401| 1: [SpecificCatchClause] catch (...) {...} +# 401| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 402| 1: [BlockStmt] {...} +# 403| 0: [EmptyStmt] ; +# 405| 2: [SpecificCatchClause] catch (...) {...} +# 405| 0: [LocalVariableDeclExpr] OverflowException ex +# 406| 1: [BlockStmt] {...} +# 407| 0: [EmptyStmt] ; +# 409| 3: [SpecificCatchClause] catch (...) {...} +# 409| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 410| 1: [BlockStmt] {...} +# 411| 0: [EmptyStmt] ; +# 413| 4: [SpecificCatchClause] catch (...) {...} +# 413| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 414| 1: [BlockStmt] {...} +# 415| 0: [EmptyStmt] ; +# 417| 5: [SpecificCatchClause] catch (...) {...} +# 417| 0: [LocalVariableDeclExpr] Exception ex +# 418| 1: [BlockStmt] {...} +# 419| 0: [EmptyStmt] ; +# 423| 21: [Method] TestRethrow +# 424| 4: [BlockStmt] {...} +# 425| 0: [TryStmt] try {...} ... +# 426| 0: [BlockStmt] {...} +# 427| 0: [TryStmt] try {...} ... +# 428| 0: [BlockStmt] {...} +# 430| 1: [GeneralCatchClause] catch {...} +# 431| 1: [BlockStmt] {...} +# 432| 0: [EmptyStmt] ; +# 433| 1: [ThrowStmt] throw ...; +# 436| 1: [SpecificCatchClause] catch (...) {...} +# 436| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 437| 1: [BlockStmt] {...} +# 438| 0: [EmptyStmt] ; +# 440| 2: [GeneralCatchClause] catch {...} +# 441| 1: [BlockStmt] {...} +# 442| 0: [EmptyStmt] ; +# 446| 22: [Method] TestSubtypeCast +# 447| 4: [BlockStmt] {...} +# 448| 0: [TryStmt] try {...} ... +# 449| 0: [BlockStmt] {...} +# 450| 0: [LocalVariableDeclStmt] ... ...; +# 450| 0: [LocalVariableDeclAndInitExpr] Object o = ... +# 450| 0: [NullLiteral] null +# 450| 1: [LocalVariableAccess] access to local variable o +# 451| 1: [EmptyStmt] ; +# 452| 2: [LocalVariableDeclStmt] ... ...; +# 452| 0: [LocalVariableDeclAndInitExpr] Class1 p = ... +# 452| 0: [CastExpr] (...) ... +# 452| 0: [LocalVariableAccess] access to local variable o +# 452| 1: [TypeAccess] access to type Class1 +# 452| 1: [LocalVariableAccess] access to local variable p +# 454| 1: [SpecificCatchClause] catch (...) {...} +# 454| 0: [LocalVariableDeclExpr] InvalidCastException ex +# 455| 1: [BlockStmt] {...} +# 456| 0: [EmptyStmt] ; +# 458| 2: [SpecificCatchClause] catch (...) {...} +# 458| 0: [LocalVariableDeclExpr] Exception ex +# 459| 1: [BlockStmt] {...} +# 460| 0: [EmptyStmt] ; +# 464| 23: [Method] TestDivideMaybeZero +#-----| 2: (Parameters) +# 464| 0: [Parameter] i +# 465| 4: [BlockStmt] {...} +# 466| 0: [TryStmt] try {...} ... +# 467| 0: [BlockStmt] {...} +# 468| 0: [EmptyStmt] ; +# 469| 1: [LocalVariableDeclStmt] ... ...; +# 469| 0: [LocalVariableDeclAndInitExpr] Int32 v = ... +# 469| 0: [DivExpr] ... / ... +# 469| 0: [IntLiteral] 1 +# 469| 1: [ParameterAccess] access to parameter i +# 469| 1: [LocalVariableAccess] access to local variable v +# 471| 1: [SpecificCatchClause] catch (...) {...} +# 471| 0: [LocalVariableDeclExpr] NullReferenceException ex +# 472| 1: [BlockStmt] {...} +# 473| 0: [EmptyStmt] ; +# 475| 2: [SpecificCatchClause] catch (...) {...} +# 475| 0: [LocalVariableDeclExpr] OverflowException ex +# 476| 1: [BlockStmt] {...} +# 477| 0: [EmptyStmt] ; +# 479| 3: [SpecificCatchClause] catch (...) {...} +# 479| 0: [LocalVariableDeclExpr] OutOfMemoryException ex +# 480| 1: [BlockStmt] {...} +# 481| 0: [EmptyStmt] ; +# 483| 4: [SpecificCatchClause] catch (...) {...} +# 483| 0: [LocalVariableDeclExpr] DivideByZeroException ex +# 484| 1: [BlockStmt] {...} +# 485| 0: [EmptyStmt] ; +# 487| 5: [SpecificCatchClause] catch (...) {...} +# 487| 0: [LocalVariableDeclExpr] Exception ex +# 488| 1: [BlockStmt] {...} +# 489| 0: [EmptyStmt] ; diff --git a/csharp/ql/test/library-tests/exceptions/PrintAst.qlref b/csharp/ql/test/library-tests/exceptions/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/exceptions/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected b/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected new file mode 100644 index 00000000000..f0e5752ac75 --- /dev/null +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation11.expected @@ -0,0 +1,3 @@ +| expressions.cs:168:27:168:44 | array creation of type Object[] | expressions.cs:168:27:168:44 | 1 | true | +| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | true | +| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | true | diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation11.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation11.ql new file mode 100644 index 00000000000..6d7a501fefa --- /dev/null +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation11.ql @@ -0,0 +1,13 @@ +/** + * @name Test for array creations + */ + +import csharp + +private boolean isImplicit(Expr expr) { + if expr.isImplicit() then result = true else result = false +} + +from ArrayCreation ac, Expr expr +where ac.isImplicitlySized() and not ac.isImplicitlyTyped() and expr = ac.getALengthArgument() +select ac, expr, isImplicit(expr) diff --git a/csharp/ql/test/library-tests/expressions/PrintAst.expected b/csharp/ql/test/library-tests/expressions/PrintAst.expected new file mode 100644 index 00000000000..0e10aa2711e --- /dev/null +++ b/csharp/ql/test/library-tests/expressions/PrintAst.expected @@ -0,0 +1,1823 @@ +FoldedLiterals.cs: +# 1| [Class] FoldedLiterals +# 3| 5: [Method] Test +# 4| 4: [BlockStmt] {...} +# 6| 0: [LocalVariableDeclStmt] ... ...; +# 6| 0: [LocalVariableDeclAndInitExpr] Boolean b1 = ... +# 6| 0: [BoolLiteral] false +# 6| 1: [LocalVariableAccess] access to local variable b1 +# 7| 1: [LocalVariableDeclStmt] ... ...; +# 7| 0: [LocalVariableDeclAndInitExpr] Boolean b2 = ... +# 7| 0: [LogicalNotExpr] !... +# 7| 0: [BoolLiteral] false +# 7| 1: [LocalVariableAccess] access to local variable b2 +# 10| 2: [LocalVariableDeclStmt] ... ...; +# 10| 0: [LocalVariableDeclAndInitExpr] Char c0 = ... +# 10| 0: [CharLiteral] +# 10| 1: [LocalVariableAccess] access to local variable c0 +# 11| 3: [LocalVariableDeclStmt] ... ...; +# 11| 0: [LocalVariableDeclAndInitExpr] Int32 c1 = ... +# 11| 0: [UnaryPlusExpr] +... +# 11| 0: [CastExpr] (...) ... +# 11| 0: [CharLiteral] +# 11| 1: [LocalVariableAccess] access to local variable c1 +# 12| 4: [LocalVariableDeclStmt] ... ...; +# 12| 0: [LocalVariableDeclAndInitExpr] Int32 c2 = ... +# 12| 0: [UnaryMinusExpr] -... +# 13| 0: [CastExpr] (...) ... +# 13| 0: [CharLiteral] +# 12| 1: [LocalVariableAccess] access to local variable c2 +# 14| 5: [LocalVariableDeclStmt] ... ...; +# 14| 0: [LocalVariableDeclAndInitExpr] Int32 c3 = ... +# 14| 0: [ComplementExpr] ~... +# 14| 0: [CastExpr] (...) ... +# 14| 0: [CharLiteral] +# 14| 1: [LocalVariableAccess] access to local variable c3 +# 15| 6: [LocalVariableDeclStmt] ... ...; +# 15| 0: [LocalVariableDeclAndInitExpr] Char c4 = ... +# 15| 0: [CharLiteral] \ +# 15| 1: [LocalVariableAccess] access to local variable c4 +# 18| 7: [LocalVariableDeclStmt] ... ...; +# 18| 0: [LocalVariableDeclAndInitExpr] SByte sb0 = ... +# 18| 0: [CastExpr] (...) ... +# 18| 0: [IntLiteral] 1 +# 18| 1: [TypeAccess] access to type SByte +# 18| 1: [LocalVariableAccess] access to local variable sb0 +# 19| 8: [LocalVariableDeclStmt] ... ...; +# 19| 0: [LocalVariableDeclAndInitExpr] Int32 sb1 = ... +# 19| 0: [UnaryPlusExpr] +... +# 19| 0: [CastExpr] (...) ... +# 19| 0: [CastExpr] (...) ... +# 19| 0: [IntLiteral] 1 +# 19| 1: [TypeAccess] access to type SByte +# 19| 1: [LocalVariableAccess] access to local variable sb1 +# 20| 9: [LocalVariableDeclStmt] ... ...; +# 20| 0: [LocalVariableDeclAndInitExpr] Int32 sb2 = ... +# 20| 0: [UnaryMinusExpr] -... +# 20| 0: [CastExpr] (...) ... +# 20| 0: [CastExpr] (...) ... +# 20| 0: [IntLiteral] 1 +# 20| 1: [TypeAccess] access to type SByte +# 20| 1: [LocalVariableAccess] access to local variable sb2 +# 21| 10: [LocalVariableDeclStmt] ... ...; +# 21| 0: [LocalVariableDeclAndInitExpr] Int32 sb3 = ... +# 21| 0: [ComplementExpr] ~... +# 21| 0: [CastExpr] (...) ... +# 21| 0: [CastExpr] (...) ... +# 21| 0: [IntLiteral] 1 +# 21| 1: [TypeAccess] access to type SByte +# 21| 1: [LocalVariableAccess] access to local variable sb3 +# 24| 11: [LocalVariableDeclStmt] ... ...; +# 24| 0: [LocalVariableDeclAndInitExpr] Byte ub0 = ... +# 24| 0: [CastExpr] (...) ... +# 24| 0: [IntLiteral] 2 +# 24| 1: [TypeAccess] access to type Byte +# 24| 1: [LocalVariableAccess] access to local variable ub0 +# 25| 12: [LocalVariableDeclStmt] ... ...; +# 25| 0: [LocalVariableDeclAndInitExpr] Int32 ub1 = ... +# 25| 0: [UnaryPlusExpr] +... +# 25| 0: [CastExpr] (...) ... +# 25| 0: [CastExpr] (...) ... +# 25| 0: [IntLiteral] 2 +# 25| 1: [TypeAccess] access to type Byte +# 25| 1: [LocalVariableAccess] access to local variable ub1 +# 26| 13: [LocalVariableDeclStmt] ... ...; +# 26| 0: [LocalVariableDeclAndInitExpr] Int32 ub2 = ... +# 26| 0: [UnaryMinusExpr] -... +# 26| 0: [CastExpr] (...) ... +# 26| 0: [CastExpr] (...) ... +# 26| 0: [IntLiteral] 2 +# 26| 1: [TypeAccess] access to type Byte +# 26| 1: [LocalVariableAccess] access to local variable ub2 +# 27| 14: [LocalVariableDeclStmt] ... ...; +# 27| 0: [LocalVariableDeclAndInitExpr] Int32 ub3 = ... +# 27| 0: [ComplementExpr] ~... +# 27| 0: [CastExpr] (...) ... +# 27| 0: [CastExpr] (...) ... +# 27| 0: [IntLiteral] 2 +# 27| 1: [TypeAccess] access to type Byte +# 27| 1: [LocalVariableAccess] access to local variable ub3 +# 30| 15: [LocalVariableDeclStmt] ... ...; +# 30| 0: [LocalVariableDeclAndInitExpr] Int16 ss0 = ... +# 30| 0: [CastExpr] (...) ... +# 30| 0: [IntLiteral] 3 +# 30| 1: [TypeAccess] access to type Int16 +# 30| 1: [LocalVariableAccess] access to local variable ss0 +# 31| 16: [LocalVariableDeclStmt] ... ...; +# 31| 0: [LocalVariableDeclAndInitExpr] Int32 ss1 = ... +# 31| 0: [UnaryPlusExpr] +... +# 31| 0: [CastExpr] (...) ... +# 31| 0: [CastExpr] (...) ... +# 31| 0: [IntLiteral] 3 +# 31| 1: [TypeAccess] access to type Int16 +# 31| 1: [LocalVariableAccess] access to local variable ss1 +# 32| 17: [LocalVariableDeclStmt] ... ...; +# 32| 0: [LocalVariableDeclAndInitExpr] Int32 ss2 = ... +# 32| 0: [UnaryMinusExpr] -... +# 32| 0: [CastExpr] (...) ... +# 32| 0: [CastExpr] (...) ... +# 32| 0: [IntLiteral] 3 +# 32| 1: [TypeAccess] access to type Int16 +# 32| 1: [LocalVariableAccess] access to local variable ss2 +# 33| 18: [LocalVariableDeclStmt] ... ...; +# 33| 0: [LocalVariableDeclAndInitExpr] Int32 ss3 = ... +# 33| 0: [ComplementExpr] ~... +# 33| 0: [CastExpr] (...) ... +# 33| 0: [CastExpr] (...) ... +# 33| 0: [IntLiteral] 3 +# 33| 1: [TypeAccess] access to type Int16 +# 33| 1: [LocalVariableAccess] access to local variable ss3 +# 36| 19: [LocalVariableDeclStmt] ... ...; +# 36| 0: [LocalVariableDeclAndInitExpr] UInt16 us0 = ... +# 36| 0: [CastExpr] (...) ... +# 36| 0: [IntLiteral] 4 +# 36| 1: [TypeAccess] access to type UInt16 +# 36| 1: [LocalVariableAccess] access to local variable us0 +# 37| 20: [LocalVariableDeclStmt] ... ...; +# 37| 0: [LocalVariableDeclAndInitExpr] Int32 us1 = ... +# 37| 0: [UnaryPlusExpr] +... +# 37| 0: [CastExpr] (...) ... +# 37| 0: [CastExpr] (...) ... +# 37| 0: [IntLiteral] 4 +# 37| 1: [TypeAccess] access to type UInt16 +# 37| 1: [LocalVariableAccess] access to local variable us1 +# 38| 21: [LocalVariableDeclStmt] ... ...; +# 38| 0: [LocalVariableDeclAndInitExpr] Int32 us2 = ... +# 38| 0: [UnaryMinusExpr] -... +# 38| 0: [CastExpr] (...) ... +# 38| 0: [CastExpr] (...) ... +# 38| 0: [IntLiteral] 4 +# 38| 1: [TypeAccess] access to type UInt16 +# 38| 1: [LocalVariableAccess] access to local variable us2 +# 39| 22: [LocalVariableDeclStmt] ... ...; +# 39| 0: [LocalVariableDeclAndInitExpr] Int32 us3 = ... +# 39| 0: [ComplementExpr] ~... +# 39| 0: [CastExpr] (...) ... +# 39| 0: [CastExpr] (...) ... +# 39| 0: [IntLiteral] 4 +# 39| 1: [TypeAccess] access to type UInt16 +# 39| 1: [LocalVariableAccess] access to local variable us3 +# 42| 23: [LocalVariableDeclStmt] ... ...; +# 42| 0: [LocalVariableDeclAndInitExpr] Int32 i0 = ... +# 42| 0: [IntLiteral] 5 +# 42| 1: [LocalVariableAccess] access to local variable i0 +# 43| 24: [LocalVariableDeclStmt] ... ...; +# 43| 0: [LocalVariableDeclAndInitExpr] Int32 i1 = ... +# 43| 0: [UnaryPlusExpr] +... +# 43| 0: [IntLiteral] 5 +# 43| 1: [LocalVariableAccess] access to local variable i1 +# 44| 25: [LocalVariableDeclStmt] ... ...; +# 44| 0: [LocalVariableDeclAndInitExpr] Int32 i2 = ... +# 44| 0: [UnaryMinusExpr] -... +# 44| 0: [IntLiteral] 5 +# 44| 1: [LocalVariableAccess] access to local variable i2 +# 45| 26: [LocalVariableDeclStmt] ... ...; +# 45| 0: [LocalVariableDeclAndInitExpr] Int32 i3 = ... +# 45| 0: [ComplementExpr] ~... +# 45| 0: [IntLiteral] 5 +# 45| 1: [LocalVariableAccess] access to local variable i3 +# 48| 27: [LocalVariableDeclStmt] ... ...; +# 48| 0: [LocalVariableDeclAndInitExpr] UInt32 ui0 = ... +# 48| 0: [CastExpr] (...) ... +# 48| 0: [IntLiteral] 6 +# 48| 1: [LocalVariableAccess] access to local variable ui0 +# 49| 28: [LocalVariableDeclStmt] ... ...; +# 49| 0: [LocalVariableDeclAndInitExpr] Int32 ui1 = ... +# 49| 0: [UnaryPlusExpr] +... +# 49| 0: [IntLiteral] 6 +# 49| 1: [LocalVariableAccess] access to local variable ui1 +# 50| 29: [LocalVariableDeclStmt] ... ...; +# 50| 0: [LocalVariableDeclAndInitExpr] Int32 ui2 = ... +# 50| 0: [UnaryMinusExpr] -... +# 50| 0: [IntLiteral] 6 +# 50| 1: [LocalVariableAccess] access to local variable ui2 +# 51| 30: [LocalVariableDeclStmt] ... ...; +# 51| 0: [LocalVariableDeclAndInitExpr] Int32 ui3 = ... +# 51| 0: [ComplementExpr] ~... +# 51| 0: [IntLiteral] 6 +# 51| 1: [LocalVariableAccess] access to local variable ui3 +# 54| 31: [LocalVariableDeclStmt] ... ...; +# 54| 0: [LocalVariableDeclAndInitExpr] Int64 l0 = ... +# 54| 0: [LongLiteral] 7 +# 54| 1: [LocalVariableAccess] access to local variable l0 +# 55| 32: [LocalVariableDeclStmt] ... ...; +# 55| 0: [LocalVariableDeclAndInitExpr] Int64 l1 = ... +# 55| 0: [UnaryPlusExpr] +... +# 55| 0: [LongLiteral] 7 +# 55| 1: [LocalVariableAccess] access to local variable l1 +# 55| 33: [EmptyStmt] ; +# 56| 34: [LocalVariableDeclStmt] ... ...; +# 56| 0: [LocalVariableDeclAndInitExpr] Int64 l2 = ... +# 56| 0: [UnaryMinusExpr] -... +# 56| 0: [LongLiteral] 7 +# 56| 1: [LocalVariableAccess] access to local variable l2 +# 57| 35: [LocalVariableDeclStmt] ... ...; +# 57| 0: [LocalVariableDeclAndInitExpr] Int64 l3 = ... +# 57| 0: [ComplementExpr] ~... +# 57| 0: [LongLiteral] 7 +# 57| 1: [LocalVariableAccess] access to local variable l3 +# 60| 36: [LocalVariableDeclStmt] ... ...; +# 60| 0: [LocalVariableDeclAndInitExpr] UInt64 ul0 = ... +# 60| 0: [ULongLiteral] 8 +# 60| 1: [LocalVariableAccess] access to local variable ul0 +# 61| 37: [LocalVariableDeclStmt] ... ...; +# 61| 0: [LocalVariableDeclAndInitExpr] UInt64 ul1 = ... +# 61| 0: [UnaryPlusExpr] +... +# 61| 0: [ULongLiteral] 8 +# 61| 1: [LocalVariableAccess] access to local variable ul1 +# 62| 38: [LocalVariableDeclStmt] ... ...; +# 62| 0: [LocalVariableDeclAndInitExpr] UInt64 ul3 = ... +# 62| 0: [ComplementExpr] ~... +# 62| 0: [ULongLiteral] 8 +# 62| 1: [LocalVariableAccess] access to local variable ul3 +# 65| 39: [LocalVariableDeclStmt] ... ...; +# 65| 0: [LocalVariableDeclAndInitExpr] Single f0 = ... +# 65| 0: [FloatLiteral] 9 +# 65| 1: [LocalVariableAccess] access to local variable f0 +# 66| 40: [LocalVariableDeclStmt] ... ...; +# 66| 0: [LocalVariableDeclAndInitExpr] Single f1 = ... +# 66| 0: [UnaryPlusExpr] +... +# 66| 0: [FloatLiteral] 9 +# 66| 1: [LocalVariableAccess] access to local variable f1 +# 67| 41: [LocalVariableDeclStmt] ... ...; +# 67| 0: [LocalVariableDeclAndInitExpr] Single f2 = ... +# 67| 0: [UnaryMinusExpr] -... +# 67| 0: [FloatLiteral] 9 +# 67| 1: [LocalVariableAccess] access to local variable f2 +# 70| 42: [LocalVariableDeclStmt] ... ...; +# 70| 0: [LocalVariableDeclAndInitExpr] Double d0 = ... +# 70| 0: [DoubleLiteral] 10 +# 70| 1: [LocalVariableAccess] access to local variable d0 +# 71| 43: [LocalVariableDeclStmt] ... ...; +# 71| 0: [LocalVariableDeclAndInitExpr] Double d1 = ... +# 71| 0: [UnaryPlusExpr] +... +# 71| 0: [DoubleLiteral] 10 +# 71| 1: [LocalVariableAccess] access to local variable d1 +# 72| 44: [LocalVariableDeclStmt] ... ...; +# 72| 0: [LocalVariableDeclAndInitExpr] Double d2 = ... +# 72| 0: [UnaryMinusExpr] -... +# 72| 0: [DoubleLiteral] 10 +# 72| 1: [LocalVariableAccess] access to local variable d2 +# 75| 45: [LocalVariableDeclStmt] ... ...; +# 75| 0: [LocalVariableDeclAndInitExpr] Decimal m0 = ... +# 75| 0: [DecimalLiteral] 11 +# 75| 1: [LocalVariableAccess] access to local variable m0 +# 76| 46: [LocalVariableDeclStmt] ... ...; +# 76| 0: [LocalVariableDeclAndInitExpr] Decimal m1 = ... +# 76| 0: [UnaryPlusExpr] +... +# 76| 0: [DecimalLiteral] 11 +# 76| 1: [LocalVariableAccess] access to local variable m1 +# 77| 47: [LocalVariableDeclStmt] ... ...; +# 77| 0: [LocalVariableDeclAndInitExpr] Decimal m2 = ... +# 77| 0: [UnaryMinusExpr] -... +# 77| 0: [DecimalLiteral] 11 +# 77| 1: [LocalVariableAccess] access to local variable m2 +MethodAccess.cs: +# 3| [Class] MethodAccess +# 5| 5: [Method] M +# 6| 4: [BlockStmt] {...} +# 7| 0: [LocalFunctionStmt] M1(...) +# 7| 0: [LocalFunction] M1 +# 7| 4: [BlockStmt] {...} +# 7| 1: [EmptyStmt] ; +# 8| 2: [LocalVariableDeclStmt] ... ...; +# 8| 0: [LocalVariableDeclAndInitExpr] Action a = ... +# 8| 0: [ImplicitDelegateCreation] delegate creation of type Action +# 8| 0: [LocalFunctionAccess] access to local function M1 +# 8| 1: [LocalVariableAccess] access to local variable a +# 9| 3: [ExprStmt] ...; +# 9| 0: [AssignExpr] ... = ... +# 9| 0: [ImplicitDelegateCreation] delegate creation of type Action +# 9| 0: [MethodAccess] access to method M2 +# 9| 1: [LocalVariableAccess] access to local variable a +# 10| 4: [ExprStmt] ...; +# 10| 0: [AssignExpr] ... = ... +# 10| 0: [ImplicitDelegateCreation] delegate creation of type Action +# 10| 0: [MethodAccess] access to method M2 +# 10| -1: [ThisAccess] this access +# 10| 1: [LocalVariableAccess] access to local variable a +# 11| 5: [ExprStmt] ...; +# 11| 0: [AssignExpr] ... = ... +# 11| 0: [ImplicitDelegateCreation] delegate creation of type Action +# 11| 0: [MethodAccess] access to method M3 +# 11| 1: [LocalVariableAccess] access to local variable a +# 12| 6: [ExprStmt] ...; +# 12| 0: [AssignExpr] ... = ... +# 12| 0: [ImplicitDelegateCreation] delegate creation of type Action +# 12| 0: [MethodAccess] access to method M3 +# 12| -1: [TypeAccess] access to type MethodAccess +# 12| 1: [LocalVariableAccess] access to local variable a +# 15| 6: [Method] M2 +# 15| 4: [BlockStmt] {...} +# 17| 7: [Method] M3 +# 17| 4: [BlockStmt] {...} +Qualifiers.cs: +# 3| [Class] Qualifiers +# 5| 5: [Property] S +# 5| 3: [Getter] get_S +# 5| 4: [MethodCall] call to method Static +# 5| 0: [NullLiteral] null +# 7| 6: [Property] I +# 7| 3: [Getter] get_I +# 7| 4: [MethodCall] call to method Instance +# 9| 7: [Property] B +# 9| 3: [Getter] get_B +# 9| 4: [MethodCall] call to method Instance +# 9| -1: [ThisAccess] this access +# 11| 8: [Method] Static +#-----| 1: (Type parameters) +# 11| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 11| 0: [Parameter] o +# 11| 4: [DefaultValueExpr] default(...) +# 11| 0: [TypeAccess] access to type T +# 13| 10: [Method] Instance +#-----| 1: (Type parameters) +# 13| 0: [TypeParameter] T +# 13| 4: [DefaultValueExpr] default(...) +# 13| 0: [TypeAccess] access to type T +ReducedExpression.cs: +# 2| [Class] ReducedClass +# 5| 5: [Field] ReducedExpression +# 5| 1: [AssignExpr] ... = ... +# 5| 0: [ConditionalExpr] ... ? ... : ... +# 5| 0: [BoolLiteral] true +# 5| 1: [IntLiteral] 10 +# 5| 2: [IntLiteral] 12 +# 5| 1: [MemberConstantAccess] access to constant ReducedExpression +expressions.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 7| 1: [Class] Class +# 10| 4: [Method] MainLiterals +# 11| 4: [BlockStmt] {...} +# 12| 0: [LocalVariableDeclStmt] ... ...; +# 12| 0: [LocalVariableDeclExpr] Boolean b +# 13| 1: [ExprStmt] ...; +# 13| 0: [AssignExpr] ... = ... +# 13| 0: [BoolLiteral] true +# 13| 1: [LocalVariableAccess] access to local variable b +# 14| 2: [ExprStmt] ...; +# 14| 0: [AssignExpr] ... = ... +# 14| 0: [BoolLiteral] false +# 14| 1: [LocalVariableAccess] access to local variable b +# 15| 3: [ExprStmt] ...; +# 15| 0: [AssignExpr] ... = ... +# 15| 0: [LogicalNotExpr] !... +# 15| 0: [LocalVariableAccess] access to local variable b +# 15| 1: [LocalVariableAccess] access to local variable b +# 16| 4: [LocalVariableDeclStmt] ... ...; +# 16| 0: [LocalVariableDeclAndInitExpr] Char c = ... +# 16| 0: [CharLiteral] @ +# 16| 1: [LocalVariableAccess] access to local variable c +# 17| 5: [LocalVariableDeclStmt] ... ...; +# 17| 0: [LocalVariableDeclExpr] Int32 i +# 18| 6: [ExprStmt] ...; +# 18| 0: [AssignExpr] ... = ... +# 18| 0: [IntLiteral] 1 +# 18| 1: [LocalVariableAccess] access to local variable i +# 19| 7: [ExprStmt] ...; +# 19| 0: [AssignExpr] ... = ... +# 19| 0: [UnaryMinusExpr] -... +# 19| 0: [LocalVariableAccess] access to local variable i +# 19| 1: [LocalVariableAccess] access to local variable i +# 20| 8: [LocalVariableDeclStmt] ... ...; +# 20| 0: [LocalVariableDeclExpr] Int64 l +# 21| 9: [ExprStmt] ...; +# 21| 0: [AssignExpr] ... = ... +# 21| 0: [LongLiteral] 8989898 +# 21| 1: [LocalVariableAccess] access to local variable l +# 22| 10: [LocalVariableDeclStmt] ... ...; +# 22| 0: [LocalVariableDeclExpr] UInt32 ui +# 23| 11: [ExprStmt] ...; +# 23| 0: [AssignExpr] ... = ... +# 23| 0: [UIntLiteral] 3 +# 23| 1: [LocalVariableAccess] access to local variable ui +# 24| 12: [LocalVariableDeclStmt] ... ...; +# 24| 0: [LocalVariableDeclExpr] UInt64 ul +# 25| 13: [ExprStmt] ...; +# 25| 0: [AssignExpr] ... = ... +# 25| 0: [ULongLiteral] 89898787897 +# 25| 1: [LocalVariableAccess] access to local variable ul +# 26| 14: [LocalVariableDeclStmt] ... ...; +# 26| 0: [LocalVariableDeclAndInitExpr] Single f = ... +# 26| 0: [FloatLiteral] 4.5 +# 26| 1: [LocalVariableAccess] access to local variable f +# 27| 15: [LocalVariableDeclStmt] ... ...; +# 27| 0: [LocalVariableDeclExpr] Double d +# 28| 16: [ExprStmt] ...; +# 28| 0: [AssignExpr] ... = ... +# 28| 0: [DoubleLiteral] 4.565 +# 28| 1: [LocalVariableAccess] access to local variable d +# 29| 17: [LocalVariableDeclStmt] ... ...; +# 29| 0: [LocalVariableDeclExpr] Decimal m +# 30| 18: [ExprStmt] ...; +# 30| 0: [AssignExpr] ... = ... +# 30| 0: [DecimalLiteral] 123.456 +# 30| 1: [LocalVariableAccess] access to local variable m +# 31| 19: [LocalVariableDeclStmt] ... ...; +# 31| 0: [LocalVariableDeclExpr] String s +# 32| 20: [ExprStmt] ...; +# 32| 0: [AssignExpr] ... = ... +# 32| 0: [StringLiteral] "test" +# 32| 1: [LocalVariableAccess] access to local variable s +# 33| 21: [LocalVariableDeclStmt] ... ...; +# 33| 0: [LocalVariableDeclExpr] Object o +# 34| 22: [ExprStmt] ...; +# 34| 0: [AssignExpr] ... = ... +# 34| 0: [NullLiteral] null +# 34| 1: [LocalVariableAccess] access to local variable o +# 37| 5: [Method] LogicalOperators +#-----| 2: (Parameters) +# 37| 0: [Parameter] a +# 37| 1: [Parameter] b +# 38| 4: [BlockStmt] {...} +# 39| 0: [LocalVariableDeclStmt] ... ...; +# 39| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 39| 0: [ConditionalExpr] ... ? ... : ... +# 39| 0: [ParameterAccess] access to parameter a +# 39| 1: [IntLiteral] 0 +# 39| 2: [IntLiteral] 42 +# 39| 1: [LocalVariableAccess] access to local variable x +# 40| 1: [LocalVariableDeclStmt] ... ...; +# 40| 0: [LocalVariableDeclAndInitExpr] Boolean c = ... +# 40| 0: [LogicalOrExpr] ... || ... +# 40| 0: [ParameterAccess] access to parameter b +# 40| 1: [GTExpr] ... > ... +# 40| 0: [LocalVariableAccess] access to local variable x +# 40| 1: [IntLiteral] 3 +# 40| 1: [LocalVariableAccess] access to local variable c +# 41| 2: [ReturnStmt] return ...; +# 41| 0: [LogicalAndExpr] ... && ... +# 41| 0: [LogicalAndExpr] ... && ... +# 41| 0: [ParameterAccess] access to parameter a +# 41| 1: [ParameterAccess] access to parameter b +# 41| 1: [LogicalNotExpr] !... +# 41| 0: [LocalVariableAccess] access to local variable c +# 44| 6: [Field] constant +# 44| 1: [AssignExpr] ... = ... +# 44| 0: [StringLiteral] "constant" +# 44| 1: [MemberConstantAccess] access to constant constant +# 45| 7: [Field] f +# 45| 1: [AssignExpr] ... = ... +# 45| 0: [IntLiteral] 0 +# 45| 1: [FieldAccess] access to field f +# 46| 8: [Field] name +# 48| 9: [StaticConstructor] Class +# 49| 4: [BlockStmt] {...} +# 51| 0: [ExprStmt] ...; +# 51| 0: [AssignExpr] ... = ... +# 51| 0: [StringLiteral] "" +# 51| 1: [FieldAccess] access to field name +# 51| -1: [TypeAccess] access to type Class +# 52| 1: [ExprStmt] ...; +# 52| 0: [MethodCall] call to method Foo +# 52| -1: [TypeAccess] access to type Class +# 53| 2: [ExprStmt] ...; +# 53| 0: [MethodCall] call to method Foo +# 56| 10: [InstanceConstructor] Class +# 56| 3: [ConstructorInitializer] call to constructor Class +# 56| 0: [IntLiteral] 0 +# 56| 4: [BlockStmt] {...} +# 58| 11: [InstanceConstructor] Class +#-----| 2: (Parameters) +# 58| 0: [Parameter] i +# 58| 4: [BlockStmt] {...} +# 60| 12: [Method] Foo +# 60| 4: [BlockStmt] {...} +# 62| 13: [Method] Bar +#-----| 2: (Parameters) +# 62| 0: [Parameter] x +# 62| 1: [Parameter] s +# 63| 4: [BlockStmt] {...} +# 64| 0: [ReturnStmt] return ...; +# 64| 0: [AddExpr] ... + ... +# 64| 0: [PropertyCall] access to property Length +# 64| -1: [ParameterAccess] access to parameter s +# 64| 1: [ParameterAccess] access to parameter x +# 67| 14: [IndexerProperty] Name +# 69| 3: [Getter] get_Name +# 69| 4: [BlockStmt] {...} +# 69| 0: [ReturnStmt] return ...; +# 69| 0: [FieldAccess] access to field name +# 70| 4: [Setter] set_Name +#-----| 2: (Parameters) +# 70| 0: [Parameter] value +# 70| 4: [BlockStmt] {...} +# 70| 0: [ExprStmt] ...; +# 70| 0: [AssignExpr] ... = ... +# 70| 0: [ParameterAccess] access to parameter value +# 70| 1: [FieldAccess] access to field name +# 73| 15: [Indexer] Item +#-----| 1: (Parameters) +# 73| 0: [Parameter] i +# 73| 1: [Parameter] s +# 75| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 73| 0: [Parameter] i +# 73| 1: [Parameter] s +# 75| 4: [BlockStmt] {...} +# 75| 0: [ReturnStmt] return ...; +# 75| 0: [LogicalAndExpr] ... && ... +# 75| 0: [GTExpr] ... > ... +# 75| 0: [ParameterAccess] access to parameter i +# 75| 1: [IntLiteral] 2 +# 75| 1: [MethodCall] call to method Equals +# 75| -1: [ParameterAccess] access to parameter s +# 75| 0: [StringLiteral] "" +# 76| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 73| 0: [Parameter] i +# 73| 1: [Parameter] s +# 76| 2: [Parameter] value +# 76| 4: [BlockStmt] {...} +# 76| 0: [IfStmt] if (...) ... +# 76| 0: [ParameterAccess] access to parameter value +# 76| 1: [ExprStmt] ...; +# 76| 0: [PostIncrExpr] ...++ +# 76| 0: [FieldAccess] access to field f +# 79| 16: [Method] MainAccesses +#-----| 2: (Parameters) +# 79| 0: [Parameter] other +# 79| 1: [Parameter] args +# 80| 4: [BlockStmt] {...} +# 81| 0: [ExprStmt] ...; +# 81| 0: [AssignExpr] ... = ... +# 81| 0: [StringLiteral] "aName" +# 81| 1: [PropertyCall] access to property Name +# 82| 1: [LocalVariableDeclStmt] ... ...; +# 82| 0: [LocalVariableDeclAndInitExpr] String n = ... +# 82| 0: [PropertyCall] access to property Name +# 82| -1: [ThisAccess] this access +# 82| 1: [LocalVariableAccess] access to local variable n +# 83| 2: [LocalVariableDeclStmt] ... ...; +# 83| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 83| 0: [MethodCall] call to method Bar +# 83| -1: [ObjectCreation] object creation of type Class +# 83| 0: [AddExpr] ... + ... +# 83| 0: [IntLiteral] 4 +# 83| 1: [IntLiteral] 2 +# 83| 1: [PropertyCall] access to property Name +# 83| 1: [LocalVariableAccess] access to local variable i +# 84| 3: [ExprStmt] ...; +# 84| 0: [AssignExpr] ... = ... +# 84| 0: [MemberConstantAccess] access to constant constant +# 84| 1: [PropertyCall] access to property Name +# 84| -1: [ParameterAccess] access to parameter other +# 85| 4: [ExprStmt] ...; +# 85| 0: [AssignExpr] ... = ... +# 85| 0: [IndexerCall] access to indexer +# 85| -1: [ThisAccess] this access +# 85| 0: [IntLiteral] 0 +# 85| 1: [StringLiteral] "" +# 85| 1: [IndexerCall] access to indexer +# 85| -1: [ParameterAccess] access to parameter other +# 85| 0: [LocalVariableAccess] access to local variable i +# 85| 1: [MemberConstantAccess] access to constant constant +# 85| -1: [TypeAccess] access to type Nested +# 86| 5: [LocalVariableDeclStmt] ... ...; +# 86| 0: [LocalVariableDeclAndInitExpr] Int32[] array = ... +# 86| 0: [ArrayCreation] array creation of type Int32[] +# 86| -1: [ArrayInitializer] { ..., ... } +# 86| 0: [CastExpr] (...) ... +# 86| 0: [ULongLiteral] 4 +# 86| 1: [TypeAccess] access to type Int32 +# 86| 1: [CastExpr] (...) ... +# 86| 0: [LongLiteral] 3 +# 86| 1: [TypeAccess] access to type Int32 +# 86| 1: [LocalVariableAccess] access to local variable array +# 87| 6: [ExprStmt] ...; +# 87| 0: [AssignExpr] ... = ... +# 87| 0: [IntLiteral] 5 +# 87| 1: [ArrayAccess] access to array element +# 87| -1: [LocalVariableAccess] access to local variable array +# 87| 0: [IntLiteral] 1 +# 91| 17: [Method] MainIsAsCast +#-----| 2: (Parameters) +# 91| 0: [Parameter] s +# 91| 1: [Parameter] o +# 91| 2: [Parameter] p +# 92| 4: [BlockStmt] {...} +# 93| 0: [IfStmt] if (...) ... +# 93| 0: [IsExpr] ... is ... +# 93| 0: [ParameterAccess] access to parameter o +# 93| 1: [TypeAccessPatternExpr] access to type Class +# 94| 1: [BlockStmt] {...} +# 95| 0: [LocalVariableDeclStmt] ... ...; +# 95| 0: [LocalVariableDeclAndInitExpr] Class c = ... +# 95| 0: [AsExpr] ... as ... +# 95| 0: [ParameterAccess] access to parameter o +# 95| 1: [TypeAccess] access to type Class +# 95| 1: [LocalVariableAccess] access to local variable c +# 96| 1: [LocalVariableDeclStmt] ... ...; +# 96| 0: [LocalVariableDeclAndInitExpr] Class d = ... +# 96| 0: [CastExpr] (...) ... +# 96| 0: [ParameterAccess] access to parameter p +# 96| 1: [TypeAccess] access to type Class +# 96| 1: [LocalVariableAccess] access to local variable d +# 98| 1: [LocalVariableDeclStmt] ... ...; +# 98| 0: [LocalVariableDeclAndInitExpr] Class x = ... +# 98| 0: [CastExpr] (...) ... +# 98| 0: [AsExpr] ... as ... +# 98| 0: [CastExpr] (...) ... +# 98| 0: [ParameterAccess] access to parameter o +# 98| 1: [TypeAccess] access to type Class +# 98| 1: [TypeAccess] access to type Object +# 98| 1: [TypeAccess] access to type Class +# 98| 1: [LocalVariableAccess] access to local variable x +# 99| 2: [LocalVariableDeclStmt] ... ...; +# 99| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 99| 0: [DefaultValueExpr] default(...) +# 99| 0: [TypeAccess] access to type Int32 +# 99| 1: [LocalVariableAccess] access to local variable i +# 100| 3: [ExprStmt] ...; +# 100| 0: [AssignExpr] ... = ... +# 100| 0: [AddExpr] ... + ... +# 100| 0: [AddExpr] ... + ... +# 100| 0: [ParameterAccess] access to parameter s +# 100| 1: [StringLiteral] " " +# 100| 1: [CastExpr] (...) ... +# 100| 0: [LocalVariableAccess] access to local variable i +# 100| 1: [ParameterAccess] access to parameter s +# 103| 18: [Class] Y<,> +#-----| 1: (Type parameters) +# 103| 0: [TypeParameter] T +# 103| 1: [TypeParameter] U +# 107| 19: [Class] X<> +#-----| 1: (Type parameters) +# 107| 0: [TypeParameter] T +# 110| 5: [Method] PrintTypes +# 111| 4: [BlockStmt] {...} +# 112| 0: [LocalVariableDeclStmt] ... ...; +# 112| 0: [LocalVariableDeclAndInitExpr] Type[] t = ... +# 112| 0: [ArrayCreation] array creation of type Type[] +# 112| -1: [ArrayInitializer] { ..., ... } +# 113| 0: [TypeofExpr] typeof(...) +# 113| 0: [TypeAccess] access to type Void +# 114| 1: [TypeofExpr] typeof(...) +# 114| 0: [TypeAccess] access to type Int32 +# 115| 2: [TypeofExpr] typeof(...) +# 115| 0: [TypeAccess] access to type Int32 +# 116| 3: [TypeofExpr] typeof(...) +# 116| 0: [TypeAccess] access to type String +# 117| 4: [TypeofExpr] typeof(...) +# 117| 0: [TypeAccess] access to type Double[] +# 118| 5: [TypeofExpr] typeof(...) +# 118| 0: [TypeAccess] access to type Void +# 119| 6: [TypeofExpr] typeof(...) +# 119| 0: [TypeAccess] access to type T +# 120| 7: [TypeofExpr] typeof(...) +# 120| 0: [TypeAccess] access to type X<> +# 121| 8: [TypeofExpr] typeof(...) +# 121| 0: [TypeAccess] access to type X> +# 122| 9: [TypeofExpr] typeof(...) +# 122| 0: [TypeAccess] access to type Y<,> +# 112| 1: [LocalVariableAccess] access to local variable t +# 124| 1: [LocalVariableDeclStmt] ... ...; +# 124| 0: [LocalVariableDeclAndInitExpr] T e = ... +# 124| 0: [DefaultValueExpr] default(...) +# 124| 0: [TypeAccess] access to type T +# 124| 1: [LocalVariableAccess] access to local variable e +# 129| 21: [Class] Nested +#-----| 3: (Base types) +# 129| 0: [Class] Class +# 133| 4: [InstanceConstructor] Nested +#-----| 2: (Parameters) +# 133| 0: [Parameter] i +# 133| 3: [ConstructorInitializer] call to constructor Class +# 133| 0: [AddExpr] ... + ... +# 133| 0: [ParameterAccess] access to parameter i +# 133| 1: [IntLiteral] 1 +# 133| 4: [BlockStmt] {...} +# 135| 5: [Method] OtherAccesses +# 136| 4: [BlockStmt] {...} +# 137| 0: [ExprStmt] ...; +# 137| 0: [AssignExpr] ... = ... +# 137| 0: [IntLiteral] 0 +# 137| 1: [FieldAccess] access to field f +# 137| -1: [ThisAccess] this access +# 138| 1: [ExprStmt] ...; +# 138| 0: [MethodCall] call to method MainAccesses +# 138| -1: [BaseAccess] base access +# 138| 0: [ThisAccess] this access +# 138| 1: [CastExpr] (...) ... +# 138| 0: [IntLiteral] 1 +# 138| 2: [CastExpr] (...) ... +# 138| 0: [IntLiteral] 2 +# 138| 3: [CastExpr] (...) ... +# 138| 0: [IntLiteral] 3 +# 138| 4: [CastExpr] (...) ... +# 138| 0: [IntLiteral] 4 +# 138| 5: [StringLiteral] "" +# 143| 22: [Method] MainLocalVarDecl +# 144| 4: [BlockStmt] {...} +# 145| 0: [LocalVariableDeclStmt] ... ...; +# 145| 0: [LocalVariableDeclExpr] Int32 a +# 146| 1: [LocalVariableDeclStmt] ... ...; +# 146| 0: [LocalVariableDeclAndInitExpr] Int32 b = ... +# 146| 0: [IntLiteral] 2 +# 146| 1: [LocalVariableAccess] access to local variable b +# 146| 1: [LocalVariableDeclAndInitExpr] Int32 c = ... +# 146| 0: [IntLiteral] 3 +# 146| 1: [LocalVariableAccess] access to local variable c +# 147| 2: [ExprStmt] ...; +# 147| 0: [AssignExpr] ... = ... +# 147| 0: [IntLiteral] 1 +# 147| 1: [LocalVariableAccess] access to local variable a +# 148| 3: [ExprStmt] ...; +# 148| 0: [MethodCall] call to method WriteLine +# 148| -1: [TypeAccess] access to type Console +# 148| 0: [AddExpr] ... + ... +# 148| 0: [AddExpr] ... + ... +# 148| 0: [LocalVariableAccess] access to local variable a +# 148| 1: [LocalVariableAccess] access to local variable b +# 148| 1: [LocalVariableAccess] access to local variable c +# 149| 4: [LocalVariableDeclStmt] ... ...; +# 149| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 149| 0: [IntLiteral] 45 +# 149| 1: [LocalVariableAccess] access to local variable x +# 150| 5: [LocalVariableDeclStmt] ... ...; +# 150| 0: [LocalVariableDeclAndInitExpr] String y = ... +# 150| 0: [StringLiteral] "test" +# 150| 1: [LocalVariableAccess] access to local variable y +# 153| 23: [Method] MainLocalConstDecl +# 154| 4: [BlockStmt] {...} +# 155| 0: [LocalConstantDeclStmt] const ... ...; +# 155| 0: [LocalVariableDeclAndInitExpr] Single pi = ... +# 155| 0: [FloatLiteral] 3.1415927 +# 155| 1: [LocalVariableAccess] access to local variable pi +# 156| 1: [LocalConstantDeclStmt] const ... ...; +# 156| 0: [LocalVariableDeclAndInitExpr] Int32 r = ... +# 156| 0: [AddExpr] ... + ... +# 156| 0: [IntLiteral] 10 +# 156| 1: [IntLiteral] 15 +# 156| 1: [LocalVariableAccess] access to local variable r +# 157| 2: [ExprStmt] ...; +# 157| 0: [MethodCall] call to method WriteLine +# 157| -1: [TypeAccess] access to type Console +# 157| 0: [MulExpr] ... * ... +# 157| 0: [MulExpr] ... * ... +# 157| 0: [LocalVariableAccess] access to local variable pi +# 157| 1: [CastExpr] (...) ... +# 157| 0: [LocalVariableAccess] access to local variable r +# 157| 1: [CastExpr] (...) ... +# 157| 0: [LocalVariableAccess] access to local variable r +# 160| 24: [Method] MainChecked +# 161| 4: [BlockStmt] {...} +# 162| 0: [LocalVariableDeclStmt] ... ...; +# 162| 0: [LocalVariableDeclAndInitExpr] String s = ... +# 162| 0: [CheckedExpr] checked (...) +# 162| 0: [PropertyCall] access to property Name +# 162| 1: [LocalVariableAccess] access to local variable s +# 163| 1: [LocalVariableDeclStmt] ... ...; +# 163| 0: [LocalVariableDeclAndInitExpr] Int32 t = ... +# 163| 0: [UncheckedExpr] unchecked (...) +# 163| 0: [AddExpr] ... + ... +# 163| 0: [FieldAccess] access to field f +# 163| 1: [IntLiteral] 20 +# 163| 1: [LocalVariableAccess] access to local variable t +# 166| 25: [Method] MainElementAccess +#-----| 2: (Parameters) +# 166| 0: [Parameter] i +# 167| 4: [BlockStmt] {...} +# 168| 0: [LocalVariableDeclStmt] ... ...; +# 168| 0: [LocalVariableDeclAndInitExpr] Object[] os = ... +# 168| 0: [ArrayCreation] array creation of type Object[] +# 168| -1: [ArrayInitializer] { ..., ... } +# 168| 0: [CastExpr] (...) ... +# 168| 0: [ParameterAccess] access to parameter i +# 168| 1: [LocalVariableAccess] access to local variable os +# 171| 26: [Method] MainDelegateAndMethodAccesses +# 172| 4: [BlockStmt] {...} +# 173| 0: [LocalVariableDeclStmt] ... ...; +# 173| 0: [LocalVariableDeclAndInitExpr] D cd1 = ... +# 173| 0: [ExplicitDelegateCreation] delegate creation of type D +# 173| 0: [MethodAccess] access to method M1 +# 173| -1: [TypeAccess] access to type C +# 173| 1: [LocalVariableAccess] access to local variable cd1 +# 174| 1: [LocalVariableDeclStmt] ... ...; +# 174| 0: [LocalVariableDeclAndInitExpr] D cd2 = ... +# 174| 0: [ImplicitDelegateCreation] delegate creation of type D +# 174| 0: [MethodAccess] access to method M2 +# 174| -1: [TypeAccess] access to type C +# 174| 1: [LocalVariableAccess] access to local variable cd2 +# 175| 2: [LocalVariableDeclStmt] ... ...; +# 175| 0: [LocalVariableDeclAndInitExpr] D cd3 = ... +# 175| 0: [OperatorCall] call to operator + +# 175| 0: [LocalVariableAccess] access to local variable cd1 +# 175| 1: [LocalVariableAccess] access to local variable cd2 +# 175| 1: [LocalVariableAccess] access to local variable cd3 +# 176| 3: [LocalVariableDeclStmt] ... ...; +# 176| 0: [LocalVariableDeclAndInitExpr] D cd4 = ... +# 176| 0: [OperatorCall] call to operator + +# 176| 0: [LocalVariableAccess] access to local variable cd3 +# 176| 1: [LocalVariableAccess] access to local variable cd1 +# 176| 1: [LocalVariableAccess] access to local variable cd4 +# 177| 4: [LocalVariableDeclStmt] ... ...; +# 177| 0: [LocalVariableDeclAndInitExpr] D cd5 = ... +# 177| 0: [OperatorCall] call to operator - +# 177| 0: [LocalVariableAccess] access to local variable cd4 +# 177| 1: [LocalVariableAccess] access to local variable cd3 +# 177| 1: [LocalVariableAccess] access to local variable cd5 +# 178| 5: [ExprStmt] ...; +# 178| 0: [AssignAddExpr] ... += ... +# 178| 0: [LocalVariableAccess] access to local variable cd5 +# 178| 1: [LocalVariableAccess] access to local variable cd4 +# 179| 6: [ExprStmt] ...; +# 179| 0: [AssignSubExpr] ... -= ... +# 179| 0: [LocalVariableAccess] access to local variable cd1 +# 179| 1: [LocalVariableAccess] access to local variable cd4 +# 181| 7: [LocalVariableDeclStmt] ... ...; +# 181| 0: [LocalVariableDeclAndInitExpr] C c = ... +# 181| 0: [ObjectCreation] object creation of type C +# 181| 1: [LocalVariableAccess] access to local variable c +# 182| 8: [LocalVariableDeclStmt] ... ...; +# 182| 0: [LocalVariableDeclAndInitExpr] D cd6 = ... +# 182| 0: [ExplicitDelegateCreation] delegate creation of type D +# 182| 0: [MethodAccess] access to method M3 +# 182| -1: [LocalVariableAccess] access to local variable c +# 182| 1: [LocalVariableAccess] access to local variable cd6 +# 183| 9: [LocalVariableDeclStmt] ... ...; +# 183| 0: [LocalVariableDeclAndInitExpr] D cd7 = ... +# 183| 0: [ExplicitDelegateCreation] delegate creation of type D +# 183| 0: [LocalVariableAccess] access to local variable cd6 +# 183| 1: [LocalVariableAccess] access to local variable cd7 +# 185| 10: [ExprStmt] ...; +# 185| 0: [DelegateCall] delegate call +# 185| -1: [LocalVariableAccess] access to local variable cd1 +# 185| 0: [UnaryMinusExpr] -... +# 185| 0: [IntLiteral] 40 +# 186| 11: [LocalVariableDeclStmt] ... ...; +# 186| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 186| 0: [IntLiteral] 0 +# 186| 1: [LocalVariableAccess] access to local variable x +# 187| 12: [ExprStmt] ...; +# 187| 0: [DelegateCall] delegate call +# 187| -1: [LocalVariableAccess] access to local variable cd7 +# 187| 0: [AddExpr] ... + ... +# 187| 0: [IntLiteral] 34 +# 187| 1: [LocalVariableAccess] access to local variable x +# 189| 13: [LocalVariableDeclStmt] ... ...; +# 189| 0: [LocalVariableDeclAndInitExpr] Predicate pi = ... +# 189| 0: [ExplicitDelegateCreation] delegate creation of type Predicate +# 189| 0: [MethodAccess] access to method F +# 189| -1: [TypeAccess] access to type X +# 189| 1: [LocalVariableAccess] access to local variable pi +# 190| 14: [LocalVariableDeclStmt] ... ...; +# 190| 0: [LocalVariableDeclAndInitExpr] Predicate ps = ... +# 190| 0: [ImplicitDelegateCreation] delegate creation of type Predicate +# 190| 0: [MethodAccess] access to method G +# 190| -1: [TypeAccess] access to type X +# 190| 1: [LocalVariableAccess] access to local variable ps +# 192| 15: [LocalVariableDeclStmt] ... ...; +# 192| 0: [LocalVariableDeclAndInitExpr] Boolean b = ... +# 192| 0: [BitwiseAndExpr] ... & ... +# 192| 0: [DelegateCall] delegate call +# 192| -1: [LocalVariableAccess] access to local variable pi +# 192| 0: [IntLiteral] 3 +# 192| 1: [DelegateCall] delegate call +# 192| -1: [LocalVariableAccess] access to local variable ps +# 192| 0: [StringLiteral] "" +# 192| 1: [LocalVariableAccess] access to local variable b +# 194| 16: [LocalVariableDeclStmt] ... ...; +# 194| 0: [LocalVariableDeclExpr] ContextCallback d +# 196| 17: [LocalFunctionStmt] LocalFunction(...) +# 196| 0: [LocalFunction] LocalFunction +#-----| 2: (Parameters) +# 196| 0: [Parameter] i +# 196| 4: [BlockStmt] {...} +# 196| 18: [EmptyStmt] ; +# 197| 19: [ExprStmt] ...; +# 197| 0: [AssignExpr] ... = ... +# 197| 0: [ExplicitDelegateCreation] delegate creation of type D +# 197| 0: [LocalFunctionAccess] access to local function LocalFunction +# 197| 1: [LocalVariableAccess] access to local variable cd1 +# 198| 20: [ExprStmt] ...; +# 198| 0: [AssignExpr] ... = ... +# 198| 0: [ImplicitDelegateCreation] delegate creation of type D +# 198| 0: [LocalFunctionAccess] access to local function LocalFunction +# 198| 1: [LocalVariableAccess] access to local variable cd1 +# 202| 2: [DelegateType] Predicate<> +#-----| 1: (Type parameters) +# 202| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 202| 0: [Parameter] value +# 204| 3: [DelegateType] D +#-----| 2: (Parameters) +# 204| 0: [Parameter] x +# 206| 4: [Class] C +# 209| 5: [Method] M1 +#-----| 2: (Parameters) +# 209| 0: [Parameter] i +# 209| 4: [BlockStmt] {...} +# 210| 6: [Method] M2 +#-----| 2: (Parameters) +# 210| 0: [Parameter] i +# 210| 4: [BlockStmt] {...} +# 211| 7: [Method] M3 +#-----| 2: (Parameters) +# 211| 0: [Parameter] i +# 211| 4: [BlockStmt] {...} +# 215| 5: [Class] X +# 218| 5: [Method] F +#-----| 2: (Parameters) +# 218| 0: [Parameter] i +# 218| 4: [BlockStmt] {...} +# 218| 0: [ReturnStmt] return ...; +# 218| 0: [LTExpr] ... < ... +# 218| 0: [ParameterAccess] access to parameter i +# 218| 1: [IntLiteral] 2 +# 220| 6: [Method] G +#-----| 2: (Parameters) +# 220| 0: [Parameter] s +# 220| 4: [BlockStmt] {...} +# 220| 0: [ReturnStmt] return ...; +# 220| 0: [BoolLiteral] false +# 224| 6: [DelegateType] EventHandler +#-----| 2: (Parameters) +# 224| 0: [Parameter] sender +# 224| 1: [Parameter] e +# 226| 7: [Class] Button +# 229| 5: [Event] Click +# 229| 3: [RemoveEventAccessor] remove_Click +#-----| 2: (Parameters) +# 229| 0: [Parameter] value +# 229| 3: [AddEventAccessor] add_Click +#-----| 2: (Parameters) +# 229| 0: [Parameter] value +# 231| 6: [Method] OnClick +#-----| 2: (Parameters) +# 231| 0: [Parameter] e +# 232| 4: [BlockStmt] {...} +# 233| 0: [IfStmt] if (...) ... +# 233| 0: [OperatorCall] call to operator != +# 233| 0: [EventAccess,EventCall] access to event Click +# 233| 1: [NullLiteral] null +# 234| 1: [ExprStmt] ...; +# 234| 0: [DelegateCall] delegate call +# 234| -1: [EventAccess,EventCall] access to event Click +# 234| 0: [ThisAccess] this access +# 234| 1: [ParameterAccess] access to parameter e +# 237| 7: [Method] Reset +# 238| 4: [BlockStmt] {...} +# 239| 0: [ExprStmt] ...; +# 239| 0: [AssignExpr] ... = ... +# 239| 0: [NullLiteral] null +# 239| 1: [EventAccess,EventCall] access to event Click +# 243| 8: [Class] LoginDialog +# 246| 4: [Field] OkButton +# 247| 5: [Field] CancelButton +# 249| 6: [InstanceConstructor] LoginDialog +# 250| 4: [BlockStmt] {...} +# 251| 0: [ExprStmt] ...; +# 251| 0: [AssignExpr] ... = ... +# 251| 0: [ObjectCreation] object creation of type Button +# 251| 1: [FieldAccess] access to field OkButton +# 252| 1: [ExprStmt] ...; +# 252| 0: [AddEventExpr] ... += ... +# 252| 0: [ExplicitDelegateCreation] delegate creation of type EventHandler +# 252| 0: [MethodAccess] access to method OkButtonClick +# 252| 1: [EventAccess,EventCall] access to event Click +# 252| -1: [FieldAccess] access to field OkButton +# 253| 2: [ExprStmt] ...; +# 253| 0: [AssignExpr] ... = ... +# 253| 0: [ObjectCreation] object creation of type Button +# 253| 1: [FieldAccess] access to field CancelButton +# 254| 3: [ExprStmt] ...; +# 254| 0: [RemoveEventExpr] ... -= ... +# 254| 0: [ExplicitDelegateCreation] delegate creation of type EventHandler +# 254| 0: [MethodAccess] access to method CancelButtonClick +# 254| 1: [EventAccess,EventCall] access to event Click +# 254| -1: [FieldAccess] access to field CancelButton +# 257| 7: [Method] OkButtonClick +#-----| 2: (Parameters) +# 257| 0: [Parameter] sender +# 257| 1: [Parameter] e +# 258| 4: [BlockStmt] {...} +# 261| 8: [Method] CancelButtonClick +#-----| 2: (Parameters) +# 261| 0: [Parameter] sender +# 261| 1: [Parameter] e +# 262| 4: [BlockStmt] {...} +# 267| 9: [Class] IntVector +# 270| 4: [InstanceConstructor] IntVector +#-----| 2: (Parameters) +# 270| 0: [Parameter] length +# 270| 4: [BlockStmt] {...} +# 272| 5: [Property] Length +# 272| 3: [Getter] get_Length +# 272| 4: [BlockStmt] {...} +# 272| 0: [ReturnStmt] return ...; +# 272| 0: [IntLiteral] 4 +# 274| 6: [Indexer] Item +#-----| 1: (Parameters) +# 274| 0: [Parameter] index +# 274| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 274| 0: [Parameter] index +# 274| 4: [BlockStmt] {...} +# 274| 0: [ReturnStmt] return ...; +# 274| 0: [IntLiteral] 0 +# 274| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 274| 0: [Parameter] index +# 274| 1: [Parameter] value +# 274| 4: [BlockStmt] {...} +# 276| 7: [IncrementOperator] ++ +#-----| 2: (Parameters) +# 276| 0: [Parameter] iv +# 277| 4: [BlockStmt] {...} +# 278| 0: [LocalVariableDeclStmt] ... ...; +# 278| 0: [LocalVariableDeclAndInitExpr] IntVector temp = ... +# 278| 0: [ObjectCreation] object creation of type IntVector +# 278| 0: [PropertyCall] access to property Length +# 278| -1: [ParameterAccess] access to parameter iv +# 278| 1: [LocalVariableAccess] access to local variable temp +# 279| 1: [ForStmt] for (...;...;...) ... +# 279| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 279| 0: [IntLiteral] 0 +# 279| 1: [LocalVariableAccess] access to local variable i +# 279| 0: [LTExpr] ... < ... +# 279| 0: [LocalVariableAccess] access to local variable i +# 279| 1: [PropertyCall] access to property Length +# 279| -1: [ParameterAccess] access to parameter iv +# 279| 1: [PostIncrExpr] ...++ +# 279| 0: [LocalVariableAccess] access to local variable i +# 280| 2: [ExprStmt] ...; +# 280| 0: [AssignExpr] ... = ... +# 280| 0: [AddExpr] ... + ... +# 280| 0: [IndexerCall] access to indexer +# 280| -1: [ParameterAccess] access to parameter iv +# 280| 0: [LocalVariableAccess] access to local variable i +# 280| 1: [IntLiteral] 1 +# 280| 1: [IndexerCall] access to indexer +# 280| -1: [LocalVariableAccess] access to local variable temp +# 280| 0: [LocalVariableAccess] access to local variable i +# 281| 2: [ReturnStmt] return ...; +# 281| 0: [LocalVariableAccess] access to local variable temp +# 284| 8: [AddOperator] + +#-----| 2: (Parameters) +# 284| 0: [Parameter] iv1 +# 284| 1: [Parameter] iv2 +# 285| 4: [BlockStmt] {...} +# 286| 0: [ReturnStmt] return ...; +# 286| 0: [ParameterAccess] access to parameter iv1 +# 291| 10: [Class] TestUnaryOperator +# 294| 5: [Method] MainUnaryOperator +# 295| 4: [BlockStmt] {...} +# 296| 0: [LocalVariableDeclStmt] ... ...; +# 296| 0: [LocalVariableDeclAndInitExpr] IntVector iv1 = ... +# 296| 0: [ObjectCreation] object creation of type IntVector +# 296| 0: [IntLiteral] 4 +# 296| 1: [LocalVariableAccess] access to local variable iv1 +# 297| 1: [LocalVariableDeclStmt] ... ...; +# 297| 0: [LocalVariableDeclExpr] IntVector iv2 +# 298| 2: [ExprStmt] ...; +# 298| 0: [AssignExpr] ... = ... +# 298| 0: [OperatorCall] call to operator ++ +# 298| 0: [LocalVariableAccess] access to local variable iv1 +# 298| 1: [LocalVariableAccess] access to local variable iv2 +# 299| 3: [ExprStmt] ...; +# 299| 0: [AssignExpr] ... = ... +# 299| 0: [OperatorCall] call to operator ++ +# 299| 0: [LocalVariableAccess] access to local variable iv1 +# 299| 1: [LocalVariableAccess] access to local variable iv2 +# 300| 4: [LocalVariableDeclStmt] ... ...; +# 300| 0: [LocalVariableDeclAndInitExpr] IntVector iv3 = ... +# 300| 0: [OperatorCall] call to operator + +# 300| 0: [LocalVariableAccess] access to local variable iv1 +# 300| 1: [LocalVariableAccess] access to local variable iv2 +# 300| 1: [LocalVariableAccess] access to local variable iv3 +# 305| 11: [Struct] Digit +# 308| 5: [Field] value +# 310| 6: [InstanceConstructor] Digit +#-----| 2: (Parameters) +# 310| 0: [Parameter] value +# 311| 4: [BlockStmt] {...} +# 312| 0: [IfStmt] if (...) ... +# 312| 0: [LogicalOrExpr] ... || ... +# 312| 0: [LTExpr] ... < ... +# 312| 0: [CastExpr] (...) ... +# 312| 0: [ParameterAccess] access to parameter value +# 312| 1: [IntLiteral] 0 +# 312| 1: [GTExpr] ... > ... +# 312| 0: [CastExpr] (...) ... +# 312| 0: [ParameterAccess] access to parameter value +# 312| 1: [IntLiteral] 9 +# 313| 1: [ThrowStmt] throw ...; +# 313| 0: [ObjectCreation] object creation of type ArgumentException +# 314| 1: [ExprStmt] ...; +# 314| 0: [AssignExpr] ... = ... +# 314| 0: [ParameterAccess] access to parameter value +# 314| 1: [FieldAccess] access to field value +# 314| -1: [ThisAccess] this access +# 317| 7: [ImplicitConversionOperator] implicit conversion +#-----| 2: (Parameters) +# 317| 0: [Parameter] d +# 318| 4: [BlockStmt] {...} +# 319| 0: [ReturnStmt] return ...; +# 319| 0: [FieldAccess] access to field value +# 319| -1: [ParameterAccess] access to parameter d +# 322| 8: [ExplicitConversionOperator] explicit conversion +#-----| 2: (Parameters) +# 322| 0: [Parameter] b +# 323| 4: [BlockStmt] {...} +# 324| 0: [ReturnStmt] return ...; +# 324| 0: [ObjectCreation] object creation of type Digit +# 324| 0: [ParameterAccess] access to parameter b +# 329| 12: [Class] TestConversionOperator +# 332| 5: [Method] MainConversionOperator +# 333| 4: [BlockStmt] {...} +# 334| 0: [LocalVariableDeclStmt] ... ...; +# 334| 0: [LocalVariableDeclAndInitExpr] Digit d = ... +# 334| 0: [OperatorCall] call to operator explicit conversion +# 334| 0: [CastExpr] (...) ... +# 334| 0: [IntLiteral] 8 +# 334| 1: [LocalVariableAccess] access to local variable d +# 335| 1: [LocalVariableDeclStmt] ... ...; +# 335| 0: [LocalVariableDeclAndInitExpr] Byte b = ... +# 335| 0: [OperatorCall] call to operator implicit conversion +# 335| 0: [LocalVariableAccess] access to local variable d +# 335| 1: [LocalVariableAccess] access to local variable b +# 340| 13: [Class] Point +# 343| 5: [Field] x +# 343| 6: [Field] y +# 345| 7: [Property] X +# 345| 3: [Getter] get_X +# 345| 4: [BlockStmt] {...} +# 345| 0: [ReturnStmt] return ...; +# 345| 0: [FieldAccess] access to field x +# 345| 4: [Setter] set_X +#-----| 2: (Parameters) +# 345| 0: [Parameter] value +# 345| 4: [BlockStmt] {...} +# 345| 0: [ExprStmt] ...; +# 345| 0: [AssignExpr] ... = ... +# 345| 0: [ParameterAccess] access to parameter value +# 345| 1: [FieldAccess] access to field x +# 346| 8: [Property] Y +# 346| 3: [Getter] get_Y +# 346| 4: [BlockStmt] {...} +# 346| 0: [ReturnStmt] return ...; +# 346| 0: [FieldAccess] access to field y +# 346| 4: [Setter] set_Y +#-----| 2: (Parameters) +# 346| 0: [Parameter] value +# 346| 4: [BlockStmt] {...} +# 346| 0: [ExprStmt] ...; +# 346| 0: [AssignExpr] ... = ... +# 346| 0: [ParameterAccess] access to parameter value +# 346| 1: [FieldAccess] access to field y +# 350| 14: [Class] Rectangle +# 353| 5: [Field] p1 +# 353| 6: [Field] p2 +# 355| 7: [Property] P1 +# 355| 3: [Getter] get_P1 +# 355| 4: [BlockStmt] {...} +# 355| 0: [ReturnStmt] return ...; +# 355| 0: [FieldAccess] access to field p1 +# 355| 4: [Setter] set_P1 +#-----| 2: (Parameters) +# 355| 0: [Parameter] value +# 355| 4: [BlockStmt] {...} +# 355| 0: [ExprStmt] ...; +# 355| 0: [AssignExpr] ... = ... +# 355| 0: [ParameterAccess] access to parameter value +# 355| 1: [FieldAccess] access to field p1 +# 356| 8: [Property] P2 +# 356| 3: [Getter] get_P2 +# 356| 4: [BlockStmt] {...} +# 356| 0: [ReturnStmt] return ...; +# 356| 0: [FieldAccess] access to field p2 +# 356| 4: [Setter] set_P2 +#-----| 2: (Parameters) +# 356| 0: [Parameter] value +# 356| 4: [BlockStmt] {...} +# 356| 0: [ExprStmt] ...; +# 356| 0: [AssignExpr] ... = ... +# 356| 0: [ParameterAccess] access to parameter value +# 356| 1: [FieldAccess] access to field p2 +# 360| 15: [Class] Rectangle2 +# 363| 5: [Field] p1 +# 363| 1: [AssignExpr] ... = ... +# 363| 0: [ObjectCreation] object creation of type Point +# 363| 1: [FieldAccess] access to field p1 +# 364| 6: [Field] p2 +# 364| 1: [AssignExpr] ... = ... +# 364| 0: [ObjectCreation] object creation of type Point +# 364| 1: [FieldAccess] access to field p2 +# 366| 7: [Property] P1 +# 366| 3: [Getter] get_P1 +# 366| 4: [BlockStmt] {...} +# 366| 0: [ReturnStmt] return ...; +# 366| 0: [FieldAccess] access to field p1 +# 367| 8: [Property] P2 +# 367| 3: [Getter] get_P2 +# 367| 4: [BlockStmt] {...} +# 367| 0: [ReturnStmt] return ...; +# 367| 0: [FieldAccess] access to field p2 +# 371| 16: [Class] Contact +# 374| 5: [Field] name +# 375| 6: [Field] phoneNumbers +# 375| 1: [AssignExpr] ... = ... +# 375| 0: [ObjectCreation] object creation of type List +# 375| 1: [FieldAccess] access to field phoneNumbers +# 377| 7: [IndexerProperty] Name +# 377| 3: [Getter] get_Name +# 377| 4: [BlockStmt] {...} +# 377| 0: [ReturnStmt] return ...; +# 377| 0: [FieldAccess] access to field name +# 377| 4: [Setter] set_Name +#-----| 2: (Parameters) +# 377| 0: [Parameter] value +# 377| 4: [BlockStmt] {...} +# 377| 0: [ExprStmt] ...; +# 377| 0: [AssignExpr] ... = ... +# 377| 0: [ParameterAccess] access to parameter value +# 377| 1: [FieldAccess] access to field name +# 378| 8: [IndexerProperty] PhoneNumbers +# 378| 3: [Getter] get_PhoneNumbers +# 378| 4: [BlockStmt] {...} +# 378| 0: [ReturnStmt] return ...; +# 378| 0: [FieldAccess] access to field phoneNumbers +# 382| 17: [Class] TestCreations +# 385| 5: [Method] MainCreations +# 386| 4: [BlockStmt] {...} +# 387| 0: [LocalVariableDeclStmt] ... ...; +# 387| 0: [LocalVariableDeclAndInitExpr] Point a = ... +# 387| 0: [ObjectCreation] object creation of type Point +# 387| -1: [ObjectInitializer] { ..., ... } +# 387| 0: [MemberInitializer] ... = ... +# 387| 0: [IntLiteral] 0 +# 387| 1: [PropertyCall] access to property X +# 387| 1: [MemberInitializer] ... = ... +# 387| 0: [IntLiteral] 1 +# 387| 1: [PropertyCall] access to property Y +# 387| 1: [LocalVariableAccess] access to local variable a +# 388| 1: [LocalVariableDeclStmt] ... ...; +# 388| 0: [LocalVariableDeclAndInitExpr] Rectangle r = ... +# 388| 0: [ObjectCreation] object creation of type Rectangle +# 389| -1: [ObjectInitializer] { ..., ... } +# 390| 0: [MemberInitializer] ... = ... +# 390| 0: [ObjectCreation] object creation of type Point +# 390| -1: [ObjectInitializer] { ..., ... } +# 390| 0: [MemberInitializer] ... = ... +# 390| 0: [IntLiteral] 0 +# 390| 1: [PropertyCall] access to property X +# 390| 1: [MemberInitializer] ... = ... +# 390| 0: [IntLiteral] 1 +# 390| 1: [PropertyCall] access to property Y +# 390| 1: [PropertyCall] access to property P1 +# 391| 1: [MemberInitializer] ... = ... +# 391| 0: [ObjectCreation] object creation of type Point +# 391| -1: [ObjectInitializer] { ..., ... } +# 391| 0: [MemberInitializer] ... = ... +# 391| 0: [IntLiteral] 2 +# 391| 1: [PropertyCall] access to property X +# 391| 1: [MemberInitializer] ... = ... +# 391| 0: [IntLiteral] 3 +# 391| 1: [PropertyCall] access to property Y +# 391| 1: [PropertyCall] access to property P2 +# 388| 1: [LocalVariableAccess] access to local variable r +# 393| 2: [LocalVariableDeclStmt] ... ...; +# 393| 0: [LocalVariableDeclAndInitExpr] Rectangle2 r2 = ... +# 393| 0: [ObjectCreation] object creation of type Rectangle2 +# 394| -1: [ObjectInitializer] { ..., ... } +# 395| 0: [MemberInitializer] ... = ... +# 395| 0: [ObjectInitializer] { ..., ... } +# 395| 0: [MemberInitializer] ... = ... +# 395| 0: [IntLiteral] 0 +# 395| 1: [PropertyCall] access to property X +# 395| 1: [MemberInitializer] ... = ... +# 395| 0: [IntLiteral] 1 +# 395| 1: [PropertyCall] access to property Y +# 395| 1: [PropertyCall] access to property P1 +# 396| 1: [MemberInitializer] ... = ... +# 396| 0: [ObjectInitializer] { ..., ... } +# 396| 0: [MemberInitializer] ... = ... +# 396| 0: [IntLiteral] 2 +# 396| 1: [PropertyCall] access to property X +# 396| 1: [MemberInitializer] ... = ... +# 396| 0: [IntLiteral] 3 +# 396| 1: [PropertyCall] access to property Y +# 396| 1: [PropertyCall] access to property P2 +# 393| 1: [LocalVariableAccess] access to local variable r2 +# 398| 3: [LocalVariableDeclStmt] ... ...; +# 398| 0: [LocalVariableDeclAndInitExpr] List digits = ... +# 398| 0: [ObjectCreation] object creation of type List +# 398| -1: [CollectionInitializer] { ..., ... } +# 398| 0: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 0 +# 398| 1: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 1 +# 398| 2: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 2 +# 398| 3: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 3 +# 398| 4: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 4 +# 398| 5: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 5 +# 398| 6: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 6 +# 398| 7: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 7 +# 398| 8: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 8 +# 398| 9: [ElementInitializer] call to method Add +# 398| 0: [IntLiteral] 9 +# 398| 1: [LocalVariableAccess] access to local variable digits +# 399| 4: [LocalVariableDeclStmt] ... ...; +# 399| 0: [LocalVariableDeclAndInitExpr] List contacts = ... +# 399| 0: [ObjectCreation] object creation of type List +# 399| -1: [CollectionInitializer] { ..., ... } +# 400| 0: [ElementInitializer] call to method Add +# 400| 0: [ObjectCreation] object creation of type Contact +# 400| -1: [ObjectInitializer] { ..., ... } +# 401| 0: [MemberInitializer] ... = ... +# 401| 0: [StringLiteral] "Chris Smith" +# 401| 1: [PropertyCall] access to property Name +# 402| 1: [MemberInitializer] ... = ... +# 402| 0: [CollectionInitializer] { ..., ... } +# 402| 0: [ElementInitializer] call to method Add +# 402| 0: [StringLiteral] "206-555-0101" +# 402| 1: [ElementInitializer] call to method Add +# 402| 0: [StringLiteral] "425-882-8080" +# 402| 1: [PropertyCall] access to property PhoneNumbers +# 404| 1: [ElementInitializer] call to method Add +# 404| 0: [ObjectCreation] object creation of type Contact +# 404| -1: [ObjectInitializer] { ..., ... } +# 405| 0: [MemberInitializer] ... = ... +# 405| 0: [StringLiteral] "Bob Harris" +# 405| 1: [PropertyCall] access to property Name +# 406| 1: [MemberInitializer] ... = ... +# 406| 0: [CollectionInitializer] { ..., ... } +# 406| 0: [ElementInitializer] call to method Add +# 406| 0: [StringLiteral] "650-555-0199" +# 406| 1: [PropertyCall] access to property PhoneNumbers +# 399| 1: [LocalVariableAccess] access to local variable contacts +# 409| 5: [LocalVariableDeclStmt] ... ...; +# 409| 0: [LocalVariableDeclAndInitExpr] Int32[,] is1 = ... +# 409| 0: [ArrayCreation] array creation of type Int32[,] +# 409| -1: [ArrayInitializer] { ..., ... } +# 409| 0: [ArrayInitializer] { ..., ... } +# 409| 0: [IntLiteral] 0 +# 409| 1: [IntLiteral] 1 +# 409| 1: [ArrayInitializer] { ..., ... } +# 409| 0: [IntLiteral] 2 +# 409| 1: [IntLiteral] 3 +# 409| 2: [ArrayInitializer] { ..., ... } +# 409| 0: [IntLiteral] 4 +# 409| 1: [IntLiteral] 5 +# 409| 1: [LocalVariableAccess] access to local variable is1 +# 410| 6: [LocalVariableDeclStmt] ... ...; +# 410| 0: [LocalVariableDeclAndInitExpr] Int32[,] is2 = ... +# 410| 0: [ArrayCreation] array creation of type Int32[,] +# 410| -1: [ArrayInitializer] { ..., ... } +# 410| 0: [ArrayInitializer] { ..., ... } +# 410| 0: [IntLiteral] 0 +# 410| 1: [IntLiteral] 1 +# 410| 1: [ArrayInitializer] { ..., ... } +# 410| 0: [IntLiteral] 2 +# 410| 1: [IntLiteral] 3 +# 410| 2: [ArrayInitializer] { ..., ... } +# 410| 0: [IntLiteral] 4 +# 410| 1: [IntLiteral] 5 +# 410| 0: [IntLiteral] 3 +# 410| 1: [IntLiteral] 2 +# 410| 1: [LocalVariableAccess] access to local variable is2 +# 411| 7: [LocalVariableDeclStmt] ... ...; +# 411| 0: [LocalVariableDeclAndInitExpr] Int32[][] is3 = ... +# 411| 0: [ArrayCreation] array creation of type Int32[][] +# 411| 0: [IntLiteral] 100 +# 411| 1: [LocalVariableAccess] access to local variable is3 +# 412| 8: [LocalVariableDeclStmt] ... ...; +# 412| 0: [LocalVariableDeclAndInitExpr] Int32[,] is4 = ... +# 412| 0: [ArrayCreation] array creation of type Int32[,] +# 412| 0: [IntLiteral] 100 +# 412| 1: [IntLiteral] 5 +# 412| 1: [LocalVariableAccess] access to local variable is4 +# 413| 9: [LocalVariableDeclStmt] ... ...; +# 413| 0: [LocalVariableDeclAndInitExpr] Int32[] is5 = ... +# 413| 0: [ArrayCreation] array creation of type Int32[] +# 413| -1: [ArrayInitializer] { ..., ... } +# 413| 0: [IntLiteral] 1 +# 413| 1: [IntLiteral] 10 +# 413| 2: [IntLiteral] 100 +# 413| 3: [IntLiteral] 1000 +# 413| 1: [LocalVariableAccess] access to local variable is5 +# 414| 10: [LocalVariableDeclStmt] ... ...; +# 414| 0: [LocalVariableDeclAndInitExpr] Double[] is6 = ... +# 414| 0: [ArrayCreation] array creation of type Double[] +# 414| -1: [ArrayInitializer] { ..., ... } +# 414| 0: [CastExpr] (...) ... +# 414| 0: [IntLiteral] 1 +# 414| 1: [DoubleLiteral] 1.5 +# 414| 2: [CastExpr] (...) ... +# 414| 0: [IntLiteral] 2 +# 414| 3: [DoubleLiteral] 2.5 +# 414| 1: [LocalVariableAccess] access to local variable is6 +# 415| 11: [LocalVariableDeclStmt] ... ...; +# 415| 0: [LocalVariableDeclAndInitExpr] String[,] is7 = ... +# 415| 0: [ArrayCreation] array creation of type String[,] +# 415| -1: [ArrayInitializer] { ..., ... } +# 415| 0: [ArrayInitializer] { ..., ... } +# 415| 0: [StringLiteral] "hello" +# 415| 1: [NullLiteral] null +# 415| 1: [ArrayInitializer] { ..., ... } +# 415| 0: [StringLiteral] "world" +# 415| 1: [StringLiteral] "!" +# 415| 1: [LocalVariableAccess] access to local variable is7 +# 416| 12: [LocalVariableDeclStmt] ... ...; +# 416| 0: [LocalVariableDeclAndInitExpr] <>__AnonType0[] contacts2 = ... +# 416| 0: [ArrayCreation] array creation of type <>__AnonType0[] +# 416| -1: [ArrayInitializer] { ..., ... } +# 417| 0: [AnonymousObjectCreation] object creation of type <>__AnonType0 +# 417| -1: [ObjectInitializer] { ..., ... } +# 418| 0: [MemberInitializer] ... = ... +# 418| 0: [StringLiteral] "Chris Smith" +# 418| 1: [PropertyCall] access to property Name +# 419| 1: [MemberInitializer] ... = ... +# 419| 0: [ArrayCreation] array creation of type String[] +# 419| -1: [ArrayInitializer] { ..., ... } +# 419| 0: [StringLiteral] "206-555-0101" +# 419| 1: [StringLiteral] "425-882-8080" +# 419| 1: [PropertyCall] access to property PhoneNumbers +# 421| 1: [AnonymousObjectCreation] object creation of type <>__AnonType0 +# 421| -1: [ObjectInitializer] { ..., ... } +# 422| 0: [MemberInitializer] ... = ... +# 422| 0: [StringLiteral] "Bob Harris" +# 422| 1: [PropertyCall] access to property Name +# 423| 1: [MemberInitializer] ... = ... +# 423| 0: [ArrayCreation] array creation of type String[] +# 423| -1: [ArrayInitializer] { ..., ... } +# 423| 0: [StringLiteral] "650-555-0199" +# 423| 1: [PropertyCall] access to property PhoneNumbers +# 416| 1: [LocalVariableAccess] access to local variable contacts2 +# 426| 13: [LocalVariableDeclStmt] ... ...; +# 426| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 426| 0: [IntLiteral] 1 +# 426| 1: [LocalVariableAccess] access to local variable i +# 427| 14: [LocalVariableDeclStmt] ... ...; +# 427| 0: [LocalVariableDeclAndInitExpr] List list1 = ... +# 427| 0: [ObjectCreation] object creation of type List +# 427| -1: [CollectionInitializer] { ..., ... } +# 427| 0: [ElementInitializer] call to method Add +# 427| 0: [AssignExpr] ... = ... +# 427| 0: [IntLiteral] 2 +# 427| 1: [LocalVariableAccess] access to local variable i +# 427| 1: [LocalVariableAccess] access to local variable list1 +# 428| 15: [LocalVariableDeclStmt] ... ...; +# 428| 0: [LocalVariableDeclAndInitExpr] List list2 = ... +# 428| 0: [ObjectCreation] object creation of type List +# 428| -1: [CollectionInitializer] { ..., ... } +# 428| 0: [ElementInitializer] call to method Add +# 428| 0: [AnonymousObjectCreation] object creation of type <>__AnonType1 +# 428| -1: [ObjectInitializer] { ..., ... } +# 428| 0: [MemberInitializer] ... = ... +# 428| 0: [IntLiteral] 2 +# 428| 1: [PropertyCall] access to property i +# 428| 1: [LocalVariableAccess] access to local variable list2 +# 429| 16: [LocalVariableDeclStmt] ... ...; +# 429| 0: [LocalVariableDeclAndInitExpr] List list3 = ... +# 429| 0: [ObjectCreation] object creation of type List +# 429| -1: [CollectionInitializer] { ..., ... } +# 429| 0: [ElementInitializer] call to method Add +# 429| 0: [EQExpr] ... == ... +# 429| 0: [LocalVariableAccess] access to local variable i +# 429| 1: [IntLiteral] 2 +# 429| 1: [LocalVariableAccess] access to local variable list3 +# 432| 6: [DelegateType] S +#-----| 2: (Parameters) +# 432| 0: [Parameter] x +# 432| 1: [Parameter] y +# 433| 7: [DelegateType] Unit +# 435| 8: [Method] MainAnonymousFunctions +# 436| 4: [BlockStmt] {...} +# 437| 0: [LocalVariableDeclStmt] ... ...; +# 437| 0: [LocalVariableDeclAndInitExpr] Func f1 = ... +# 437| 0: [LambdaExpr] (...) => ... +# 437| 0: [CastExpr] (...) ... +# 437| 0: [AddExpr] ... + ... +# 437| 0: [CastExpr] (...) ... +# 437| 0: [ParameterAccess] access to parameter x +# 437| 1: [IntLiteral] 1 +# 437| 1: [TypeAccess] access to type Byte +#-----| 2: (Parameters) +# 437| 0: [Parameter] x +# 437| 1: [LocalVariableAccess] access to local variable f1 +# 438| 1: [LocalVariableDeclStmt] ... ...; +# 438| 0: [LocalVariableDeclAndInitExpr] Func f2 = ... +# 438| 0: [LambdaExpr] (...) => ... +# 438| 0: [BlockStmt] {...} +# 438| 0: [ReturnStmt] return ...; +# 438| 0: [CastExpr] (...) ... +# 438| 0: [AddExpr] ... + ... +# 438| 0: [ParameterAccess] access to parameter x +# 438| 1: [IntLiteral] 1 +#-----| 2: (Parameters) +# 438| 0: [Parameter] x +# 438| 1: [LocalVariableAccess] access to local variable f2 +# 439| 2: [LocalVariableDeclStmt] ... ...; +# 439| 0: [LocalVariableDeclAndInitExpr] Func f3 = ... +# 439| 0: [LambdaExpr] (...) => ... +# 439| 0: [AddExpr] ... + ... +# 439| 0: [ParameterAccess] access to parameter x +# 439| 1: [IntLiteral] 1 +#-----| 2: (Parameters) +# 439| 0: [Parameter] x +# 439| 1: [LocalVariableAccess] access to local variable f3 +# 440| 3: [LocalVariableDeclStmt] ... ...; +# 440| 0: [LocalVariableDeclAndInitExpr] Func f4 = ... +# 440| 0: [LambdaExpr] (...) => ... +# 440| 0: [BlockStmt] {...} +# 440| 0: [ReturnStmt] return ...; +# 440| 0: [AddExpr] ... + ... +# 440| 0: [CastExpr] (...) ... +# 440| 0: [ParameterAccess] access to parameter x +# 440| 1: [StringLiteral] "" +#-----| 2: (Parameters) +# 440| 0: [Parameter] x +# 440| 1: [LocalVariableAccess] access to local variable f4 +# 441| 4: [LocalVariableDeclStmt] ... ...; +# 441| 0: [LocalVariableDeclAndInitExpr] S f5 = ... +# 441| 0: [LambdaExpr] (...) => ... +# 441| 0: [MulExpr] ... * ... +# 441| 0: [ParameterAccess] access to parameter x +# 441| 1: [ParameterAccess] access to parameter y +#-----| 2: (Parameters) +# 441| 0: [Parameter] x +# 441| 1: [Parameter] y +# 441| 1: [LocalVariableAccess] access to local variable f5 +# 442| 5: [LocalVariableDeclStmt] ... ...; +# 442| 0: [LocalVariableDeclAndInitExpr] Unit f6 = ... +# 442| 0: [LambdaExpr] (...) => ... +# 442| 0: [MethodCall] call to method WriteLine +# 442| -1: [TypeAccess] access to type Console +# 442| 1: [LocalVariableAccess] access to local variable f6 +# 443| 6: [LocalVariableDeclStmt] ... ...; +# 443| 0: [LocalVariableDeclAndInitExpr] Func f7 = ... +# 443| 0: [AnonymousMethodExpr] delegate(...) { ... } +# 443| 0: [BlockStmt] {...} +# 443| 0: [ReturnStmt] return ...; +# 443| 0: [AddExpr] ... + ... +# 443| 0: [ParameterAccess] access to parameter x +# 443| 1: [IntLiteral] 1 +#-----| 2: (Parameters) +# 443| 0: [Parameter] x +# 443| 1: [LocalVariableAccess] access to local variable f7 +# 444| 7: [LocalVariableDeclStmt] ... ...; +# 444| 0: [LocalVariableDeclAndInitExpr] Int32 j = ... +# 444| 0: [IntLiteral] 0 +# 444| 1: [LocalVariableAccess] access to local variable j +# 445| 8: [LocalVariableDeclStmt] ... ...; +# 445| 0: [LocalVariableDeclAndInitExpr] Func f8 = ... +# 445| 0: [AnonymousMethodExpr] delegate(...) { ... } +# 445| 0: [BlockStmt] {...} +# 445| 0: [ReturnStmt] return ...; +# 445| 0: [AddExpr] ... + ... +# 445| 0: [LocalVariableAccess] access to local variable j +# 445| 1: [IntLiteral] 1 +# 445| 1: [LocalVariableAccess] access to local variable f8 +# 450| 18: [Class] OperatorCalls +# 452| 5: [Method] delegateCombine +#-----| 2: (Parameters) +# 452| 0: [Parameter] fun +# 453| 4: [BlockStmt] {...} +# 454| 0: [LocalVariableDeclStmt] ... ...; +# 454| 0: [LocalVariableDeclAndInitExpr] MyDelegate PropertyChanged = ... +# 454| 0: [NullLiteral] null +# 454| 1: [LocalVariableAccess] access to local variable PropertyChanged +# 455| 1: [ExprStmt] ...; +# 455| 0: [AssignAddExpr] ... += ... +# 455| 0: [ParameterAccess] access to parameter fun +# 455| 1: [LocalVariableAccess] access to local variable PropertyChanged +# 458| 6: [Method] addition +#-----| 2: (Parameters) +# 458| 0: [Parameter] a +# 458| 1: [Parameter] b +# 458| 2: [Parameter] c +# 459| 4: [BlockStmt] {...} +# 460| 0: [LocalVariableDeclStmt] ... ...; +# 460| 0: [LocalVariableDeclAndInitExpr] Num result = ... +# 460| 0: [OperatorCall] call to operator + +# 460| 0: [ParameterAccess] access to parameter a +# 460| 1: [ParameterAccess] access to parameter b +# 460| 1: [LocalVariableAccess] access to local variable result +# 461| 1: [ExprStmt] ...; +# 461| 0: [AssignAddExpr] ... += ... +# 461| 0: [ParameterAccess] access to parameter c +# 461| 1: [LocalVariableAccess] access to local variable result +# 462| 2: [ReturnStmt] return ...; +# 462| 0: [LocalVariableAccess] access to local variable result +# 464| 7: [Class] Num +# 466| 4: [Field] value +# 468| 5: [InstanceConstructor] Num +#-----| 2: (Parameters) +# 468| 0: [Parameter] value +# 469| 4: [BlockStmt] {...} +# 470| 0: [ExprStmt] ...; +# 470| 0: [AssignExpr] ... = ... +# 470| 0: [ParameterAccess] access to parameter value +# 470| 1: [FieldAccess] access to field value +# 470| -1: [ThisAccess] this access +# 473| 6: [AddOperator] + +#-----| 2: (Parameters) +# 473| 0: [Parameter] c1 +# 473| 1: [Parameter] c2 +# 474| 4: [BlockStmt] {...} +# 475| 0: [ReturnStmt] return ...; +# 475| 0: [ObjectCreation] object creation of type Num +# 475| 0: [AddExpr] ... + ... +# 475| 0: [FieldAccess] access to field value +# 475| -1: [ParameterAccess] access to parameter c1 +# 475| 1: [FieldAccess] access to field value +# 475| -1: [ParameterAccess] access to parameter c2 +# 479| 8: [DelegateType] MyDelegate +#-----| 2: (Parameters) +# 479| 0: [Parameter] e +# 482| 19: [Class] ExpressionDepth +# 484| 5: [Field] d +# 484| 1: [AssignExpr] ... = ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [AddExpr] ... + ... +# 484| 0: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 484| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 485| 1: [IntLiteral] 1 +# 484| 1: [MemberConstantAccess] access to constant d +# 488| 20: [Class] TupleExprs +# 490| 5: [Method] Test +# 491| 4: [BlockStmt] {...} +# 492| 0: [LocalVariableDeclStmt] ... ...; +# 492| 0: [LocalVariableDeclAndInitExpr] (Int32,String) a = ... +# 492| 0: [DefaultValueExpr] default(...) +# 492| 0: [TypeAccess] access to type (Int32,String) +# 492| 1: [LocalVariableAccess] access to local variable a +# 493| 1: [LocalVariableDeclStmt] ... ...; +# 493| 0: [LocalVariableDeclAndInitExpr] (Boolean,Int32[],Object) b = ... +# 493| 0: [DefaultValueExpr] default(...) +# 493| 0: [TypeAccess] access to type (Boolean,Int32[],Object) +# 493| 1: [LocalVariableAccess] access to local variable b +# 494| 2: [LocalVariableDeclStmt] ... ...; +# 494| 0: [LocalVariableDeclAndInitExpr] Type x = ... +# 494| 0: [TypeofExpr] typeof(...) +# 494| 0: [TypeAccess] access to type (Int32,String) +# 494| 1: [LocalVariableAccess] access to local variable x +# 495| 3: [LocalVariableDeclStmt] ... ...; +# 495| 0: [LocalVariableDeclAndInitExpr] Type y = ... +# 495| 0: [TypeofExpr] typeof(...) +# 495| 0: [TypeAccess] access to type (Boolean,Int32[],dynamic) +# 495| 1: [LocalVariableAccess] access to local variable y diff --git a/csharp/ql/test/library-tests/expressions/PrintAst.qlref b/csharp/ql/test/library-tests/expressions/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/expressions/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/fields/PrintAst.expected b/csharp/ql/test/library-tests/fields/PrintAst.expected new file mode 100644 index 00000000000..b87bd043db2 --- /dev/null +++ b/csharp/ql/test/library-tests/fields/PrintAst.expected @@ -0,0 +1,185 @@ +fields.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 7| 1: [Class] A +# 10| 6: [Field] X +# 10| 1: [AssignExpr] ... = ... +# 10| 0: [IntLiteral] 1 +# 10| 1: [FieldAccess] access to field X +# 10| 7: [Field] Y +# 10| 8: [Field] Z +# 10| 1: [AssignExpr] ... = ... +# 10| 0: [IntLiteral] 100 +# 10| 1: [FieldAccess] access to field Z +# 13| 2: [Class] B +# 15| 6: [Field] X +# 15| 1: [AssignExpr] ... = ... +# 15| 0: [IntLiteral] 1 +# 15| 1: [FieldAccess] access to field X +# 16| 7: [Field] Y +# 17| 8: [Field] Z +# 17| 1: [AssignExpr] ... = ... +# 17| 0: [IntLiteral] 100 +# 17| 1: [FieldAccess] access to field Z +# 20| 3: [Class] C<> +#-----| 1: (Type parameters) +# 20| 0: [TypeParameter] V +# 23| 5: [Field] count +# 23| 1: [AssignExpr] ... = ... +# 23| 0: [IntLiteral] 0 +# 23| 1: [FieldAccess] access to field count +# 25| 6: [InstanceConstructor] C +# 25| 4: [BlockStmt] {...} +# 25| 0: [ExprStmt] ...; +# 25| 0: [PostIncrExpr] ...++ +# 25| 0: [FieldAccess] access to field count +# 27| 7: [Property] Count +# 27| 3: [Getter] get_Count +# 27| 4: [BlockStmt] {...} +# 27| 0: [ReturnStmt] return ...; +# 27| 0: [FieldAccess] access to field count +# 31| 4: [Class] Application +# 34| 6: [Field] finished +# 35| 7: [Field] x +# 35| 1: [AssignExpr] ... = ... +# 35| 0: [MethodCall] call to method Sqrt +# 35| -1: [TypeAccess] access to type Math +# 35| 0: [DoubleLiteral] 2 +# 35| 1: [FieldAccess] access to field x +# 36| 8: [Field] i +# 36| 1: [AssignExpr] ... = ... +# 36| 0: [IntLiteral] 100 +# 36| 1: [FieldAccess] access to field i +# 37| 9: [Field] s +# 37| 1: [AssignExpr] ... = ... +# 37| 0: [StringLiteral] "Hello" +# 37| 1: [FieldAccess] access to field s +# 39| 10: [Method] Main +# 40| 4: [BlockStmt] {...} +# 41| 0: [LocalVariableDeclStmt] ... ...; +# 41| 0: [LocalVariableDeclAndInitExpr] Decimal d = ... +# 41| 0: [MemberConstantAccess] access to constant MaxValue +# 41| -1: [TypeAccess] access to type Decimal +# 41| 1: [LocalVariableAccess] access to local variable d +# 42| 1: [LocalVariableDeclStmt] ... ...; +# 42| 0: [LocalVariableDeclAndInitExpr] C x1 = ... +# 42| 0: [ObjectCreation] object creation of type C +# 42| 1: [LocalVariableAccess] access to local variable x1 +# 43| 2: [ExprStmt] ...; +# 43| 0: [MethodCall] call to method WriteLine +# 43| -1: [TypeAccess] access to type Console +# 43| 0: [PropertyCall] access to property Count +# 43| -1: [TypeAccess] access to type C +# 44| 3: [LocalVariableDeclStmt] ... ...; +# 44| 0: [LocalVariableDeclAndInitExpr] C x2 = ... +# 44| 0: [ObjectCreation] object creation of type C +# 44| 1: [LocalVariableAccess] access to local variable x2 +# 45| 4: [ExprStmt] ...; +# 45| 0: [MethodCall] call to method WriteLine +# 45| -1: [TypeAccess] access to type Console +# 45| 0: [PropertyCall] access to property Count +# 45| -1: [TypeAccess] access to type C +# 50| 5: [Class] Color +# 53| 5: [Field] Black +# 53| 1: [AssignExpr] ... = ... +# 53| 0: [ObjectCreation] object creation of type Color +# 53| 0: [CastExpr] (...) ... +# 53| 0: [IntLiteral] 0 +# 53| 1: [CastExpr] (...) ... +# 53| 0: [IntLiteral] 0 +# 53| 2: [CastExpr] (...) ... +# 53| 0: [IntLiteral] 0 +# 53| 1: [FieldAccess] access to field Black +# 54| 6: [Field] White +# 54| 1: [AssignExpr] ... = ... +# 54| 0: [ObjectCreation] object creation of type Color +# 54| 0: [CastExpr] (...) ... +# 54| 0: [IntLiteral] 255 +# 54| 1: [CastExpr] (...) ... +# 54| 0: [IntLiteral] 255 +# 54| 2: [CastExpr] (...) ... +# 54| 0: [IntLiteral] 255 +# 54| 1: [FieldAccess] access to field White +# 56| 7: [InstanceConstructor] Color +#-----| 2: (Parameters) +# 56| 0: [Parameter] r +# 56| 1: [Parameter] g +# 56| 2: [Parameter] b +# 56| 4: [BlockStmt] {...} +# 60| 6: [Class] TestBindings +# 63| 6: [Field] a +# 63| 1: [AssignExpr] ... = ... +# 63| 0: [AddExpr] ... + ... +# 63| 0: [FieldAccess] access to field b +# 63| 1: [IntLiteral] 1 +# 63| 1: [FieldAccess] access to field a +# 64| 7: [Field] b +# 64| 1: [AssignExpr] ... = ... +# 64| 0: [AddExpr] ... + ... +# 64| 0: [FieldAccess] access to field a +# 64| 1: [IntLiteral] 1 +# 64| 1: [FieldAccess] access to field b +# 70| [NamespaceDeclaration] namespace ... { ... } +# 72| 1: [Class] A +# 74| 5: [Field] X +# 74| 1: [AssignExpr] ... = ... +# 74| 0: [AddExpr] ... + ... +# 74| 0: [MemberConstantAccess] access to constant Z +# 74| -1: [TypeAccess] access to type B +# 74| 1: [IntLiteral] 1 +# 74| 1: [MemberConstantAccess] access to constant X +# 75| 6: [Field] Y +# 75| 1: [AssignExpr] ... = ... +# 75| 0: [IntLiteral] 10 +# 75| 1: [MemberConstantAccess] access to constant Y +# 78| 2: [Class] B +# 80| 5: [Field] Z +# 80| 1: [AssignExpr] ... = ... +# 80| 0: [AddExpr] ... + ... +# 80| 0: [MemberConstantAccess] access to constant Y +# 80| -1: [TypeAccess] access to type A +# 80| 1: [IntLiteral] 1 +# 80| 1: [MemberConstantAccess] access to constant Z +# 83| 3: [Class] C +# 85| 4: [Field] Foo +# 85| 1: [AssignExpr] ... = ... +# 85| 0: [IntLiteral] 1 +# 85| 1: [MemberConstantAccess] access to constant Foo +# 86| 5: [Field] x +# 87| 6: [InstanceConstructor] C +# 88| 4: [BlockStmt] {...} +# 89| 0: [ExprStmt] ...; +# 89| 0: [AssignExpr] ... = ... +# 89| 0: [CastExpr] (...) ... +# 89| 0: [MemberConstantAccess] access to constant Foo +# 89| 1: [FieldAccess] access to field x +# 90| 1: [LocalVariableDeclStmt] ... ...; +# 90| 0: [LocalVariableDeclAndInitExpr] dynamic dyn = ... +# 90| 0: [CastExpr] (...) ... +# 90| 0: [MemberConstantAccess] access to constant Foo +# 90| 1: [LocalVariableAccess] access to local variable dyn +# 91| 2: [LocalVariableDeclStmt] ... ...; +# 91| 0: [LocalVariableDeclAndInitExpr] D d = ... +# 91| 0: [OperatorCall] call to operator implicit conversion +# 91| 0: [MemberConstantAccess] access to constant Foo +# 91| 1: [LocalVariableAccess] access to local variable d +# 92| 3: [LocalVariableDeclStmt] ... ...; +# 92| 0: [LocalVariableDeclAndInitExpr] C c = ... +# 92| 0: [ObjectCreation] object creation of type C +# 92| -1: [ObjectInitializer] { ..., ... } +# 92| 0: [MemberInitializer] ... = ... +# 92| 0: [CastExpr] (...) ... +# 92| 0: [MemberConstantAccess] access to constant Foo +# 92| 1: [FieldAccess] access to field x +# 92| 1: [LocalVariableAccess] access to local variable c +# 96| 4: [Class] D +# 98| 4: [InstanceConstructor] D +#-----| 2: (Parameters) +# 98| 0: [Parameter] d +# 99| 4: [BlockStmt] {...} +# 101| 5: [ImplicitConversionOperator] implicit conversion +#-----| 2: (Parameters) +# 101| 0: [Parameter] d +# 101| 4: [BlockStmt] {...} +# 101| 0: [ReturnStmt] return ...; +# 101| 0: [ObjectCreation] object creation of type D +# 101| 0: [ParameterAccess] access to parameter d diff --git a/csharp/ql/test/library-tests/fields/PrintAst.qlref b/csharp/ql/test/library-tests/fields/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/fields/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/generics/PrintAst.expected b/csharp/ql/test/library-tests/generics/PrintAst.expected new file mode 100644 index 00000000000..3bdb250f7f0 --- /dev/null +++ b/csharp/ql/test/library-tests/generics/PrintAst.expected @@ -0,0 +1,547 @@ +Nesting.cs: +# 1| [Class] A<> +#-----| 1: (Type parameters) +# 1| 0: [TypeParameter] T1 +# 3| 5: [Method] MA1 +#-----| 2: (Parameters) +# 3| 0: [Parameter] x +# 3| 4: [BlockStmt] {...} +# 4| 6: [Method] MA2 +#-----| 1: (Type parameters) +# 4| 0: [TypeParameter] T2 +#-----| 2: (Parameters) +# 4| 0: [Parameter] x +# 4| 1: [Parameter] y +# 4| 4: [BlockStmt] {...} +# 6| 7: [Class] B<> +#-----| 1: (Type parameters) +# 6| 0: [TypeParameter] T3 +# 8| 5: [Method] MB1 +#-----| 2: (Parameters) +# 8| 0: [Parameter] x +# 8| 1: [Parameter] y +# 8| 4: [BlockStmt] {...} +# 9| 6: [Method] MB2 +#-----| 1: (Type parameters) +# 9| 0: [TypeParameter] T4 +#-----| 2: (Parameters) +# 9| 0: [Parameter] x +# 9| 1: [Parameter] y +# 9| 2: [Parameter] z +# 9| 4: [BlockStmt] {...} +# 12| 8: [Class] C +# 14| 5: [Method] MC1 +#-----| 2: (Parameters) +# 14| 0: [Parameter] x +# 14| 4: [BlockStmt] {...} +# 15| 6: [Method] MC2 +#-----| 1: (Type parameters) +# 15| 0: [TypeParameter] T5 +#-----| 2: (Parameters) +# 15| 0: [Parameter] x +# 15| 1: [Parameter] y +# 15| 4: [BlockStmt] {...} +# 17| 7: [Class] D<> +#-----| 1: (Type parameters) +# 17| 0: [TypeParameter] T6 +# 19| 5: [Method] MD1 +#-----| 2: (Parameters) +# 19| 0: [Parameter] x +# 19| 1: [Parameter] y +# 19| 4: [BlockStmt] {...} +# 20| 6: [Method] MD2 +#-----| 1: (Type parameters) +# 20| 0: [TypeParameter] T7 +#-----| 2: (Parameters) +# 20| 0: [Parameter] x +# 20| 1: [Parameter] y +# 20| 2: [Parameter] z +# 20| 4: [BlockStmt] {...} +# 24| 9: [Method] Construct +# 25| 4: [BlockStmt] {...} +# 26| 0: [LocalVariableDeclStmt] ... ...; +# 26| 0: [LocalVariableDeclAndInitExpr] A a1 = ... +# 26| 0: [ObjectCreation] object creation of type A +# 26| 1: [LocalVariableAccess] access to local variable a1 +# 27| 1: [ExprStmt] ...; +# 27| 0: [MethodCall] call to method MA1 +# 27| -1: [LocalVariableAccess] access to local variable a1 +# 27| 0: [IntLiteral] 0 +# 28| 2: [ExprStmt] ...; +# 28| 0: [MethodCall] call to method MA2 +# 28| -1: [LocalVariableAccess] access to local variable a1 +# 28| 0: [IntLiteral] 0 +# 28| 1: [StringLiteral] "" +# 30| 3: [LocalVariableDeclStmt] ... ...; +# 30| 0: [LocalVariableDeclAndInitExpr] A a2 = ... +# 30| 0: [ObjectCreation] object creation of type A +# 30| 1: [LocalVariableAccess] access to local variable a2 +# 31| 4: [ExprStmt] ...; +# 31| 0: [MethodCall] call to method MA1 +# 31| -1: [LocalVariableAccess] access to local variable a2 +# 31| 0: [StringLiteral] "" +# 32| 5: [ExprStmt] ...; +# 32| 0: [MethodCall] call to method MA2 +# 32| -1: [LocalVariableAccess] access to local variable a2 +# 32| 0: [StringLiteral] "" +# 32| 1: [IntLiteral] 0 +# 34| 6: [LocalVariableDeclStmt] ... ...; +# 34| 0: [LocalVariableDeclAndInitExpr] B b1 = ... +# 34| 0: [ObjectCreation] object creation of type B +# 34| 1: [LocalVariableAccess] access to local variable b1 +# 35| 7: [ExprStmt] ...; +# 35| 0: [MethodCall] call to method MB1 +# 35| -1: [LocalVariableAccess] access to local variable b1 +# 35| 0: [IntLiteral] 0 +# 35| 1: [StringLiteral] "" +# 36| 8: [ExprStmt] ...; +# 36| 0: [MethodCall] call to method MB2 +# 36| -1: [LocalVariableAccess] access to local variable b1 +# 36| 0: [IntLiteral] 0 +# 36| 1: [StringLiteral] "" +# 36| 2: [BoolLiteral] false +# 38| 9: [LocalVariableDeclStmt] ... ...; +# 38| 0: [LocalVariableDeclAndInitExpr] B b2 = ... +# 38| 0: [ObjectCreation] object creation of type B +# 38| 1: [LocalVariableAccess] access to local variable b2 +# 39| 10: [ExprStmt] ...; +# 39| 0: [MethodCall] call to method MB1 +# 39| -1: [LocalVariableAccess] access to local variable b2 +# 39| 0: [StringLiteral] "" +# 39| 1: [IntLiteral] 0 +# 40| 11: [ExprStmt] ...; +# 40| 0: [MethodCall] call to method MB2 +# 40| -1: [LocalVariableAccess] access to local variable b2 +# 40| 0: [StringLiteral] "" +# 40| 1: [IntLiteral] 0 +# 40| 2: [BoolLiteral] false +# 42| 12: [LocalVariableDeclStmt] ... ...; +# 42| 0: [LocalVariableDeclAndInitExpr] C c1 = ... +# 42| 0: [ObjectCreation] object creation of type C +# 42| 1: [LocalVariableAccess] access to local variable c1 +# 43| 13: [ExprStmt] ...; +# 43| 0: [MethodCall] call to method MC1 +# 43| -1: [LocalVariableAccess] access to local variable c1 +# 43| 0: [IntLiteral] 0 +# 44| 14: [ExprStmt] ...; +# 44| 0: [MethodCall] call to method MC2 +# 44| -1: [LocalVariableAccess] access to local variable c1 +# 44| 0: [IntLiteral] 0 +# 44| 1: [BoolLiteral] false +# 46| 15: [LocalVariableDeclStmt] ... ...; +# 46| 0: [LocalVariableDeclAndInitExpr] C c2 = ... +# 46| 0: [ObjectCreation] object creation of type C +# 46| 1: [LocalVariableAccess] access to local variable c2 +# 47| 16: [ExprStmt] ...; +# 47| 0: [MethodCall] call to method MC1 +# 47| -1: [LocalVariableAccess] access to local variable c2 +# 47| 0: [StringLiteral] "" +# 48| 17: [ExprStmt] ...; +# 48| 0: [MethodCall] call to method MC2 +# 48| -1: [LocalVariableAccess] access to local variable c2 +# 48| 0: [StringLiteral] "" +# 48| 1: [BoolLiteral] false +# 50| 18: [LocalVariableDeclStmt] ... ...; +# 50| 0: [LocalVariableDeclAndInitExpr] D d1 = ... +# 50| 0: [ObjectCreation] object creation of type D +# 50| 1: [LocalVariableAccess] access to local variable d1 +# 51| 19: [ExprStmt] ...; +# 51| 0: [MethodCall] call to method MD1 +# 51| -1: [LocalVariableAccess] access to local variable d1 +# 51| 0: [IntLiteral] 0 +# 51| 1: [BoolLiteral] false +# 52| 20: [ExprStmt] ...; +# 52| 0: [MethodCall] call to method MD2 +# 52| -1: [LocalVariableAccess] access to local variable d1 +# 52| 0: [IntLiteral] 0 +# 52| 1: [BoolLiteral] false +# 52| 2: [StringLiteral] "" +# 54| 21: [LocalVariableDeclStmt] ... ...; +# 54| 0: [LocalVariableDeclAndInitExpr] D d2 = ... +# 54| 0: [ObjectCreation] object creation of type D +# 54| 1: [LocalVariableAccess] access to local variable d2 +# 55| 22: [ExprStmt] ...; +# 55| 0: [MethodCall] call to method MD1 +# 55| -1: [LocalVariableAccess] access to local variable d2 +# 55| 0: [StringLiteral] "" +# 55| 1: [DecimalLiteral] 0 +# 56| 23: [ExprStmt] ...; +# 56| 0: [MethodCall] call to method MD2 +# 56| -1: [LocalVariableAccess] access to local variable d2 +# 56| 0: [StringLiteral] "" +# 56| 1: [DecimalLiteral] 0 +# 56| 2: [BoolLiteral] false +generics.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 7| 1: [DelegateType] GenericDelegate<> +#-----| 1: (Type parameters) +# 7| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 7| 0: [Parameter] t +# 9| 2: [Class] A +# 13| 3: [Class] A<> +#-----| 1: (Type parameters) +# 13| 0: [TypeParameter] T +# 16| 5: [DelegateType] GenericDelegateInGenericClass<> +#-----| 1: (Type parameters) +# 16| 0: [TypeParameter] U +#-----| 2: (Parameters) +# 16| 0: [Parameter] t +# 16| 1: [Parameter] u +# 18| 6: [Method] bar +#-----| 1: (Type parameters) +# 18| 0: [TypeParameter] X +#-----| 2: (Parameters) +# 18| 0: [Parameter] x +# 18| 1: [Parameter] t +# 18| 4: [BlockStmt] {...} +# 18| 0: [LocalVariableDeclStmt] ... ...; +# 18| 0: [LocalVariableDeclExpr] A<> a +# 18| 1: [ReturnStmt] return ...; +# 18| 0: [ParameterAccess] access to parameter t +# 22| 4: [Class] B<> +#-----| 1: (Type parameters) +# 22| 0: [TypeParameter] T +# 25| 5: [Field] at +# 27| 6: [Field] name +# 29| 7: [Method] foo +# 29| 4: [BlockStmt] {...} +# 31| 8: [Method] fooParams +#-----| 2: (Parameters) +# 31| 0: [Parameter] ts +# 31| 4: [BlockStmt] {...} +# 33| 9: [Method] staticFoo +# 33| 4: [BlockStmt] {...} +# 35| 10: [IndexerProperty] Name +# 35| 3: [Getter] get_Name +# 35| 4: [BlockStmt] {...} +# 35| 0: [ReturnStmt] return ...; +# 35| 0: [FieldAccess] access to field name +# 35| 4: [Setter] set_Name +#-----| 2: (Parameters) +# 35| 0: [Parameter] value +# 35| 4: [BlockStmt] {...} +# 35| 0: [ExprStmt] ...; +# 35| 0: [AssignExpr] ... = ... +# 35| 0: [ParameterAccess] access to parameter value +# 35| 1: [FieldAccess] access to field name +# 37| 11: [Event] myEvent +# 37| 3: [AddEventAccessor] add_myEvent +#-----| 2: (Parameters) +# 37| 0: [Parameter] value +# 37| 3: [RemoveEventAccessor] remove_myEvent +#-----| 2: (Parameters) +# 37| 0: [Parameter] value +# 39| 12: [IncrementOperator] ++ +#-----| 2: (Parameters) +# 39| 0: [Parameter] a +# 40| 4: [BlockStmt] {...} +# 41| 0: [ReturnStmt] return ...; +# 41| 0: [ObjectCreation] object creation of type B<> +# 44| 13: [Destructor] ~B +# 44| 4: [BlockStmt] {...} +# 45| 14: [Method] f +#-----| 1: (Type parameters) +# 45| 0: [TypeParameter] X +# 45| 4: [BlockStmt] {...} +# 45| 0: [ExprStmt] ...; +# 45| 0: [ObjectCreation] object creation of type B +# 48| 5: [Class] Outer<> +#-----| 1: (Type parameters) +# 48| 0: [TypeParameter] T +# 51| 5: [Class] Inner<> +#-----| 1: (Type parameters) +# 51| 0: [TypeParameter] U +# 54| 5: [Field] t +# 55| 6: [Field] myFunc +# 60| 6: [Class] Grid<> +#-----| 1: (Type parameters) +# 60| 0: [TypeParameter] T +# 63| 5: [Field] NumRows +# 63| 1: [AssignExpr] ... = ... +# 63| 0: [IntLiteral] 26 +# 63| 1: [MemberConstantAccess] access to constant NumRows +# 64| 6: [Field] NumCols +# 64| 1: [AssignExpr] ... = ... +# 64| 0: [IntLiteral] 10 +# 64| 1: [MemberConstantAccess] access to constant NumCols +# 66| 7: [Field] cells +# 66| 1: [AssignExpr] ... = ... +# 66| 0: [ArrayCreation] array creation of type T[,] +# 66| 0: [MemberConstantAccess] access to constant NumRows +# 66| 1: [MemberConstantAccess] access to constant NumCols +# 66| 1: [FieldAccess] access to field cells +# 68| 8: [Indexer] Item +#-----| 1: (Parameters) +# 68| 0: [Parameter] i +# 70| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 68| 0: [Parameter] i +# 70| 4: [BlockStmt] {...} +# 70| 0: [ReturnStmt] return ...; +# 70| 0: [ParameterAccess] access to parameter i +# 73| 9: [Indexer] Item +#-----| 1: (Parameters) +# 73| 0: [Parameter] c +# 73| 1: [Parameter] col +# 75| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 73| 0: [Parameter] c +# 73| 1: [Parameter] col +# 76| 4: [BlockStmt] {...} +# 77| 0: [ExprStmt] ...; +# 77| 0: [AssignExpr] ... = ... +# 77| 0: [MethodCall] call to method ToUpper +# 77| -1: [TypeAccess] access to type Char +# 77| 0: [ParameterAccess] access to parameter c +# 77| 1: [ParameterAccess] access to parameter c +# 78| 1: [IfStmt] if (...) ... +# 78| 0: [LogicalOrExpr] ... || ... +# 78| 0: [LTExpr] ... < ... +# 78| 0: [CastExpr] (...) ... +# 78| 0: [ParameterAccess] access to parameter c +# 78| 1: [CastExpr] (...) ... +# 78| 0: [CharLiteral] A +# 78| 1: [GTExpr] ... > ... +# 78| 0: [CastExpr] (...) ... +# 78| 0: [ParameterAccess] access to parameter c +# 78| 1: [CastExpr] (...) ... +# 78| 0: [CharLiteral] Z +# 79| 1: [BlockStmt] {...} +# 80| 0: [ThrowStmt] throw ...; +# 80| 0: [ObjectCreation] object creation of type ArgumentException +# 82| 2: [IfStmt] if (...) ... +# 82| 0: [LogicalOrExpr] ... || ... +# 82| 0: [LTExpr] ... < ... +# 82| 0: [ParameterAccess] access to parameter col +# 82| 1: [IntLiteral] 0 +# 82| 1: [GEExpr] ... >= ... +# 82| 0: [ParameterAccess] access to parameter col +# 82| 1: [MemberConstantAccess] access to constant NumCols +# 83| 1: [BlockStmt] {...} +# 84| 0: [ThrowStmt] throw ...; +# 84| 0: [ObjectCreation] object creation of type IndexOutOfRangeException +# 86| 3: [ReturnStmt] return ...; +# 86| 0: [ArrayAccess] access to array element +# 86| -1: [FieldAccess] access to field cells +# 86| 0: [SubExpr] ... - ... +# 86| 0: [CastExpr] (...) ... +# 86| 0: [ParameterAccess] access to parameter c +# 86| 1: [CastExpr] (...) ... +# 86| 0: [CharLiteral] A +# 86| 1: [ParameterAccess] access to parameter col +# 88| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 73| 0: [Parameter] c +# 73| 1: [Parameter] col +# 88| 2: [Parameter] value +# 89| 4: [BlockStmt] {...} +# 90| 0: [ExprStmt] ...; +# 90| 0: [AssignExpr] ... = ... +# 90| 0: [MethodCall] call to method ToUpper +# 90| -1: [TypeAccess] access to type Char +# 90| 0: [ParameterAccess] access to parameter c +# 90| 1: [ParameterAccess] access to parameter c +# 91| 1: [IfStmt] if (...) ... +# 91| 0: [LogicalOrExpr] ... || ... +# 91| 0: [LTExpr] ... < ... +# 91| 0: [CastExpr] (...) ... +# 91| 0: [ParameterAccess] access to parameter c +# 91| 1: [CastExpr] (...) ... +# 91| 0: [CharLiteral] A +# 91| 1: [GTExpr] ... > ... +# 91| 0: [CastExpr] (...) ... +# 91| 0: [ParameterAccess] access to parameter c +# 91| 1: [CastExpr] (...) ... +# 91| 0: [CharLiteral] Z +# 92| 1: [BlockStmt] {...} +# 93| 0: [ThrowStmt] throw ...; +# 93| 0: [ObjectCreation] object creation of type ArgumentException +# 95| 2: [IfStmt] if (...) ... +# 95| 0: [LogicalOrExpr] ... || ... +# 95| 0: [LTExpr] ... < ... +# 95| 0: [ParameterAccess] access to parameter col +# 95| 1: [IntLiteral] 0 +# 95| 1: [GEExpr] ... >= ... +# 95| 0: [ParameterAccess] access to parameter col +# 95| 1: [MemberConstantAccess] access to constant NumCols +# 96| 1: [BlockStmt] {...} +# 97| 0: [ThrowStmt] throw ...; +# 97| 0: [ObjectCreation] object creation of type IndexOutOfRangeException +# 99| 3: [ExprStmt] ...; +# 99| 0: [AssignExpr] ... = ... +# 99| 0: [ParameterAccess] access to parameter value +# 99| 1: [ArrayAccess] access to array element +# 99| -1: [FieldAccess] access to field cells +# 99| 0: [SubExpr] ... - ... +# 99| 0: [CastExpr] (...) ... +# 99| 0: [ParameterAccess] access to parameter c +# 99| 1: [CastExpr] (...) ... +# 99| 0: [CharLiteral] A +# 99| 1: [ParameterAccess] access to parameter col +# 105| 7: [Class] Test +# 108| 5: [Method] Main +# 109| 4: [BlockStmt] {...} +# 110| 0: [LocalVariableDeclStmt] ... ...; +# 110| 0: [LocalVariableDeclAndInitExpr] B bs = ... +# 110| 0: [ObjectCreation] object creation of type B +# 110| 1: [LocalVariableAccess] access to local variable bs +# 111| 1: [ExprStmt] ...; +# 111| 0: [AssignExpr] ... = ... +# 111| 0: [ObjectCreation] object creation of type A +# 111| 1: [FieldAccess] access to field at +# 111| -1: [LocalVariableAccess] access to local variable bs +# 112| 2: [ExprStmt] ...; +# 112| 0: [MethodCall] call to method foo +# 112| -1: [LocalVariableAccess] access to local variable bs +# 113| 3: [ExprStmt] ...; +# 113| 0: [MethodCall] call to method fooParams +# 113| -1: [LocalVariableAccess] access to local variable bs +# 113| 0: [StringLiteral] "a" +# 113| 1: [StringLiteral] "b" +# 115| 4: [ExprStmt] ...; +# 115| 0: [MethodCall] call to method staticFoo +# 115| -1: [TypeAccess] access to type B +# 117| 5: [ExprStmt] ...; +# 117| 0: [AssignExpr] ... = ... +# 117| 0: [StringLiteral] "" +# 117| 1: [PropertyCall] access to property Name +# 117| -1: [LocalVariableAccess] access to local variable bs +# 118| 6: [ExprStmt] ...; +# 118| 0: [AddEventExpr] ... += ... +# 118| 0: [ExplicitDelegateCreation] delegate creation of type GenericDelegate +# 118| 0: [MethodAccess] access to method f +# 118| 1: [EventAccess,EventCall] access to event myEvent +# 118| -1: [LocalVariableAccess] access to local variable bs +# 119| 7: [ExprStmt] ...; +# 119| 0: [OperatorCall] call to operator ++ +# 119| 0: [LocalVariableAccess] access to local variable bs +# 121| 8: [LocalVariableDeclStmt] ... ...; +# 121| 0: [LocalVariableDeclAndInitExpr] Grid g = ... +# 121| 0: [ObjectCreation] object creation of type Grid +# 121| 1: [LocalVariableAccess] access to local variable g +# 122| 9: [LocalVariableDeclStmt] ... ...; +# 122| 0: [LocalVariableDeclAndInitExpr] Int32 j = ... +# 122| 0: [IndexerCall] access to indexer +# 122| -1: [LocalVariableAccess] access to local variable g +# 122| 0: [CharLiteral] e +# 122| 1: [IntLiteral] 1 +# 122| 1: [LocalVariableAccess] access to local variable j +# 124| 10: [ExprStmt] ...; +# 124| 0: [AssignExpr] ... = ... +# 124| 0: [CastExpr] (...) ... +# 124| 0: [IntLiteral] 3 +# 124| 1: [FieldAccess] access to field t +# 124| -1: [ObjectCreation] object creation of type Inner +# 126| 11: [ExprStmt] ...; +# 126| 0: [MethodCall] call to method bar +# 126| -1: [ObjectCreation] object creation of type A +# 126| 0: [IntLiteral] 2 +# 126| 1: [StringLiteral] "" +# 127| 12: [ExprStmt] ...; +# 127| 0: [MethodCall] call to method bar +# 127| -1: [ObjectCreation] object creation of type A +# 127| 0: [ObjectCreation] object creation of type Test +# 127| 1: [IntLiteral] 2 +# 130| 6: [Method] f +#-----| 2: (Parameters) +# 130| 0: [Parameter] s +# 130| 4: [BlockStmt] {...} +# 130| 0: [ReturnStmt] return ...; +# 130| 0: [ParameterAccess] access to parameter s +# 134| 8: [Class] Subtle +# 137| 5: [Method] fs +#-----| 1: (Type parameters) +# 137| 0: [TypeParameter] X +#-----| 2: (Parameters) +# 137| 0: [Parameter] i +# 137| 4: [BlockStmt] {...} +# 139| 6: [Method] fs +#-----| 1: (Type parameters) +# 139| 0: [TypeParameter] X +#-----| 2: (Parameters) +# 139| 0: [Parameter] i +# 139| 1: [Parameter] j +# 139| 4: [BlockStmt] {...} +# 141| 7: [Method] fs +#-----| 2: (Parameters) +# 141| 0: [Parameter] i +# 141| 4: [BlockStmt] {...} +# 145| 9: [Class] Param<> +#-----| 1: (Type parameters) +# 145| 0: [TypeParameter] T +# 147| 5: [Enum] E +# 147| 5: [Field] x +# 150| 10: [Class] ConstructedMethods +# 152| 5: [Method] CM1 +#-----| 1: (Type parameters) +# 152| 0: [TypeParameter] T +# 152| 4: [BlockStmt] {...} +# 153| 8: [Method] CM2 +#-----| 1: (Type parameters) +# 153| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 153| 0: [Parameter] t +# 153| 4: [BlockStmt] {...} +# 153| 0: [ReturnStmt] return ...; +# 153| 0: [ParameterAccess] access to parameter t +# 155| 11: [Class] Class<> +#-----| 1: (Type parameters) +# 155| 0: [TypeParameter] T1 +# 157| 5: [Method] CM3 +#-----| 1: (Type parameters) +# 157| 0: [TypeParameter] T2 +#-----| 2: (Parameters) +# 157| 0: [Parameter] t +# 157| 1: [Parameter] t1 +# 157| 4: [BlockStmt] {...} +# 157| 0: [ReturnStmt] return ...; +# 157| 0: [ParameterAccess] access to parameter t +# 160| 14: [Method] NonCM +# 160| 4: [BlockStmt] {...} +# 162| 15: [Method] CM +# 163| 4: [BlockStmt] {...} +# 164| 0: [ExprStmt] ...; +# 164| 0: [MethodCall] call to method CM1 +# 165| 1: [ExprStmt] ...; +# 165| 0: [MethodCall] call to method CM1 +# 166| 2: [ExprStmt] ...; +# 166| 0: [MethodCall] call to method CM2 +# 166| 0: [IntLiteral] 4 +# 167| 3: [ExprStmt] ...; +# 167| 0: [MethodCall] call to method CM2 +# 167| 0: [DoubleLiteral] 2 +# 168| 4: [ExprStmt] ...; +# 168| 0: [MethodCall] call to method CM3 +# 168| -1: [ObjectCreation] object creation of type Class +# 168| 0: [DoubleLiteral] 1 +# 168| 1: [IntLiteral] 2 +# 169| 5: [ExprStmt] ...; +# 169| 0: [MethodCall] call to method CM3 +# 169| -1: [ObjectCreation] object creation of type Class +# 169| 0: [DoubleLiteral] 1 +# 169| 1: [DoubleLiteral] 2 +# 173| 11: [Interface] Interface<> +#-----| 1: (Type parameters) +# 173| 0: [TypeParameter] T +# 175| 4: [Method] set +#-----| 2: (Parameters) +# 175| 0: [Parameter] t +# 178| 12: [Class] Inheritance<> +#-----| 1: (Type parameters) +# 178| 0: [TypeParameter] T +#-----| 3: (Base types) +# 178| 1: [Interface] Interface +# 180| 5: [Method] set +#-----| 2: (Parameters) +# 180| 0: [Parameter] t +# 180| 4: [BlockStmt] {...} +# 183| 13: [Class] InheritanceTest +# 185| 5: [Field] member +# 188| 14: [Interface] Interface2<,> +#-----| 1: (Type parameters) +# 188| 0: [TypeParameter] T1 +# 188| 1: [TypeParameter] T2 +# 190| 4: [Method] M +#-----| 2: (Parameters) +# 190| 0: [Parameter] x diff --git a/csharp/ql/test/library-tests/generics/PrintAst.qlref b/csharp/ql/test/library-tests/generics/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/generics/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/goto/PrintAst.expected b/csharp/ql/test/library-tests/goto/PrintAst.expected new file mode 100644 index 00000000000..7ee79e8ded2 --- /dev/null +++ b/csharp/ql/test/library-tests/goto/PrintAst.expected @@ -0,0 +1,42 @@ +goto.cs: +# 2| [Class] Goto +# 4| 5: [Method] Main +# 5| 4: [BlockStmt] {...} +# 6| 0: [BlockStmt] {...} +# 7| 0: [LabelStmt] s1: +# 7| 1: [GotoLabelStmt] goto ...; +# 9| 1: [LabelStmt] s2: +# 9| 2: [LocalVariableDeclStmt] ... ...; +# 9| 0: [LocalVariableDeclAndInitExpr] String s = ... +# 9| 0: [StringLiteral] "5" +# 9| 1: [LocalVariableAccess] access to local variable s +# 10| 3: [SwitchStmt] switch (...) {...} +# 10| 0: [LocalVariableAccess] access to local variable s +# 12| 0: [ConstCase] case ...: +# 12| 0: [ConstantPatternExpr,NullLiteral] null +# 12| 1: [LabelStmt] s3: +# 12| 2: [GotoCaseStmt] goto case ...; +# 12| 0: [StringLiteral] "1" +# 13| 3: [ConstCase] case ...: +# 13| 0: [ConstantPatternExpr,StringLiteral] "1" +# 13| 4: [LabelStmt] s4: +# 13| 5: [GotoCaseStmt] goto case ...; +# 13| 0: [StringLiteral] "2" +# 14| 6: [ConstCase] case ...: +# 14| 0: [ConstantPatternExpr,StringLiteral] "2" +# 14| 7: [LabelStmt] s5: +# 14| 8: [GotoLabelStmt] goto ...; +# 15| 9: [ConstCase] case ...: +# 15| 0: [ConstantPatternExpr,StringLiteral] "3" +# 15| 10: [LabelStmt] s6: +# 15| 11: [GotoDefaultStmt] goto default; +# 16| 12: [ConstCase] case ...: +# 16| 0: [ConstantPatternExpr,StringLiteral] "4" +# 16| 13: [LabelStmt] s7: +# 16| 14: [BreakStmt] break; +# 17| 15: [DefaultCase] default: +# 17| 16: [LabelStmt] s8: +# 17| 17: [GotoCaseStmt] goto case ...; +# 17| 0: [NullLiteral] null +# 19| 4: [LabelStmt] s9: +# 19| 5: [EmptyStmt] ; diff --git a/csharp/ql/test/library-tests/goto/PrintAst.qlref b/csharp/ql/test/library-tests/goto/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/goto/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/indexers/PrintAst.expected b/csharp/ql/test/library-tests/indexers/PrintAst.expected new file mode 100644 index 00000000000..57f4bac0ef9 --- /dev/null +++ b/csharp/ql/test/library-tests/indexers/PrintAst.expected @@ -0,0 +1,322 @@ +indexers.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 8| 1: [Class] BitArray +# 11| 4: [Field] bits +# 12| 5: [Field] length +# 14| 6: [InstanceConstructor] BitArray +#-----| 2: (Parameters) +# 14| 0: [Parameter] length +# 15| 4: [BlockStmt] {...} +# 16| 0: [IfStmt] if (...) ... +# 16| 0: [LTExpr] ... < ... +# 16| 0: [ParameterAccess] access to parameter length +# 16| 1: [IntLiteral] 0 +# 17| 1: [ThrowStmt] throw ...; +# 17| 0: [ObjectCreation] object creation of type ArgumentException +# 18| 1: [ExprStmt] ...; +# 18| 0: [AssignExpr] ... = ... +# 18| 0: [ArrayCreation] array creation of type Int32[] +# 18| 0: [AddExpr] ... + ... +# 18| 0: [RShiftExpr] ... >> ... +# 18| 0: [SubExpr] ... - ... +# 18| 0: [ParameterAccess] access to parameter length +# 18| 1: [IntLiteral] 1 +# 18| 1: [IntLiteral] 5 +# 18| 1: [IntLiteral] 1 +# 18| 1: [FieldAccess] access to field bits +# 19| 2: [ExprStmt] ...; +# 19| 0: [AssignExpr] ... = ... +# 19| 0: [ParameterAccess] access to parameter length +# 19| 1: [FieldAccess] access to field length +# 19| -1: [ThisAccess] this access +# 22| 7: [Property] Length +# 22| 3: [Getter] get_Length +# 22| 4: [BlockStmt] {...} +# 22| 0: [ReturnStmt] return ...; +# 22| 0: [FieldAccess] access to field length +# 24| 8: [Indexer] Item +#-----| 1: (Parameters) +# 24| 0: [Parameter] index +# 26| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 24| 0: [Parameter] index +# 27| 4: [BlockStmt] {...} +# 28| 0: [IfStmt] if (...) ... +# 28| 0: [LogicalOrExpr] ... || ... +# 28| 0: [LTExpr] ... < ... +# 28| 0: [ParameterAccess] access to parameter index +# 28| 1: [IntLiteral] 0 +# 28| 1: [GEExpr] ... >= ... +# 28| 0: [ParameterAccess] access to parameter index +# 28| 1: [FieldAccess] access to field length +# 29| 1: [BlockStmt] {...} +# 30| 0: [ThrowStmt] throw ...; +# 30| 0: [ObjectCreation] object creation of type IndexOutOfRangeException +# 32| 1: [ReturnStmt] return ...; +# 32| 0: [NEExpr] ... != ... +# 32| 0: [BitwiseAndExpr] ... & ... +# 32| 0: [ArrayAccess] access to array element +# 32| -1: [FieldAccess] access to field bits +# 32| 0: [RShiftExpr] ... >> ... +# 32| 0: [ParameterAccess] access to parameter index +# 32| 1: [IntLiteral] 5 +# 32| 1: [LShiftExpr] ... << ... +# 32| 0: [IntLiteral] 1 +# 32| 1: [ParameterAccess] access to parameter index +# 32| 1: [IntLiteral] 0 +# 34| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 24| 0: [Parameter] index +# 34| 1: [Parameter] value +# 35| 4: [BlockStmt] {...} +# 36| 0: [IfStmt] if (...) ... +# 36| 0: [LogicalOrExpr] ... || ... +# 36| 0: [LTExpr] ... < ... +# 36| 0: [ParameterAccess] access to parameter index +# 36| 1: [IntLiteral] 0 +# 36| 1: [GEExpr] ... >= ... +# 36| 0: [ParameterAccess] access to parameter index +# 36| 1: [FieldAccess] access to field length +# 37| 1: [BlockStmt] {...} +# 38| 0: [ThrowStmt] throw ...; +# 38| 0: [ObjectCreation] object creation of type IndexOutOfRangeException +# 40| 1: [IfStmt] if (...) ... +# 40| 0: [ParameterAccess] access to parameter value +# 41| 1: [BlockStmt] {...} +# 42| 0: [ExprStmt] ...; +# 42| 0: [AssignOrExpr] ... |= ... +# 42| 0: [LShiftExpr] ... << ... +# 42| 0: [IntLiteral] 1 +# 42| 1: [ParameterAccess] access to parameter index +# 42| 1: [ArrayAccess] access to array element +# 42| -1: [FieldAccess] access to field bits +# 42| 0: [RShiftExpr] ... >> ... +# 42| 0: [ParameterAccess] access to parameter index +# 42| 1: [IntLiteral] 5 +# 45| 2: [BlockStmt] {...} +# 46| 0: [ExprStmt] ...; +# 46| 0: [AssignAndExpr] ... &= ... +# 46| 0: [ComplementExpr] ~... +# 46| 0: [LShiftExpr] ... << ... +# 46| 0: [IntLiteral] 1 +# 46| 1: [ParameterAccess] access to parameter index +# 46| 1: [ArrayAccess] access to array element +# 46| -1: [FieldAccess] access to field bits +# 46| 0: [RShiftExpr] ... >> ... +# 46| 0: [ParameterAccess] access to parameter index +# 46| 1: [IntLiteral] 5 +# 53| 2: [Class] CountPrimes +# 56| 5: [Method] Count +#-----| 2: (Parameters) +# 56| 0: [Parameter] max +# 57| 4: [BlockStmt] {...} +# 58| 0: [LocalVariableDeclStmt] ... ...; +# 58| 0: [LocalVariableDeclAndInitExpr] BitArray flags = ... +# 58| 0: [ObjectCreation] object creation of type BitArray +# 58| 0: [AddExpr] ... + ... +# 58| 0: [ParameterAccess] access to parameter max +# 58| 1: [IntLiteral] 1 +# 58| 1: [LocalVariableAccess] access to local variable flags +# 59| 1: [LocalVariableDeclStmt] ... ...; +# 59| 0: [LocalVariableDeclAndInitExpr] Int32 count = ... +# 59| 0: [IntLiteral] 1 +# 59| 1: [LocalVariableAccess] access to local variable count +# 60| 2: [ForStmt] for (...;...;...) ... +# 60| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 60| 0: [IntLiteral] 2 +# 60| 1: [LocalVariableAccess] access to local variable i +# 60| 0: [LEExpr] ... <= ... +# 60| 0: [LocalVariableAccess] access to local variable i +# 60| 1: [ParameterAccess] access to parameter max +# 60| 1: [PostIncrExpr] ...++ +# 60| 0: [LocalVariableAccess] access to local variable i +# 61| 2: [BlockStmt] {...} +# 62| 0: [IfStmt] if (...) ... +# 62| 0: [LogicalNotExpr] !... +# 62| 0: [IndexerCall] access to indexer +# 62| -1: [LocalVariableAccess] access to local variable flags +# 62| 0: [LocalVariableAccess] access to local variable i +# 63| 1: [BlockStmt] {...} +# 64| 0: [ForStmt] for (...;...;...) ... +# 64| -1: [LocalVariableDeclAndInitExpr] Int32 j = ... +# 64| 0: [MulExpr] ... * ... +# 64| 0: [LocalVariableAccess] access to local variable i +# 64| 1: [IntLiteral] 2 +# 64| 1: [LocalVariableAccess] access to local variable j +# 64| 0: [LEExpr] ... <= ... +# 64| 0: [LocalVariableAccess] access to local variable j +# 64| 1: [ParameterAccess] access to parameter max +# 64| 1: [AssignAddExpr] ... += ... +# 64| 0: [LocalVariableAccess] access to local variable i +# 64| 1: [LocalVariableAccess] access to local variable j +# 65| 2: [ExprStmt] ...; +# 65| 0: [AssignExpr] ... = ... +# 65| 0: [BoolLiteral] true +# 65| 1: [IndexerCall] access to indexer +# 65| -1: [LocalVariableAccess] access to local variable flags +# 65| 0: [LocalVariableAccess] access to local variable j +# 66| 1: [ExprStmt] ...; +# 66| 0: [PostIncrExpr] ...++ +# 66| 0: [LocalVariableAccess] access to local variable count +# 69| 3: [ReturnStmt] return ...; +# 69| 0: [LocalVariableAccess] access to local variable count +# 72| 6: [Method] Main +#-----| 2: (Parameters) +# 72| 0: [Parameter] args +# 73| 4: [BlockStmt] {...} +# 74| 0: [LocalVariableDeclStmt] ... ...; +# 74| 0: [LocalVariableDeclAndInitExpr] Int32 max = ... +# 74| 0: [MethodCall] call to method Parse +# 74| -1: [TypeAccess] access to type Int32 +# 74| 0: [ArrayAccess] access to array element +# 74| -1: [ParameterAccess] access to parameter args +# 74| 0: [IntLiteral] 0 +# 74| 1: [LocalVariableAccess] access to local variable max +# 75| 1: [LocalVariableDeclStmt] ... ...; +# 75| 0: [LocalVariableDeclAndInitExpr] Int32 count = ... +# 75| 0: [MethodCall] call to method Count +# 75| 0: [LocalVariableAccess] access to local variable max +# 75| 1: [LocalVariableAccess] access to local variable count +# 76| 2: [ExprStmt] ...; +# 76| 0: [MethodCall] call to method WriteLine +# 76| -1: [TypeAccess] access to type Console +# 76| 0: [StringLiteral] "Found {0} primes between 1 and {1}" +# 76| 1: [CastExpr] (...) ... +# 76| 0: [LocalVariableAccess] access to local variable count +# 76| 2: [CastExpr] (...) ... +# 76| 0: [LocalVariableAccess] access to local variable max +# 81| 3: [Class] Grid +# 84| 5: [Field] NumRows +# 84| 1: [AssignExpr] ... = ... +# 84| 0: [IntLiteral] 26 +# 84| 1: [MemberConstantAccess] access to constant NumRows +# 85| 6: [Field] NumCols +# 85| 1: [AssignExpr] ... = ... +# 85| 0: [IntLiteral] 10 +# 85| 1: [MemberConstantAccess] access to constant NumCols +# 87| 7: [Field] cells +# 87| 1: [AssignExpr] ... = ... +# 87| 0: [ArrayCreation] array creation of type Int32[,] +# 87| 0: [MemberConstantAccess] access to constant NumRows +# 87| 1: [MemberConstantAccess] access to constant NumCols +# 87| 1: [FieldAccess] access to field cells +# 89| 8: [Indexer] Item +#-----| 1: (Parameters) +# 89| 0: [Parameter] c +# 89| 1: [Parameter] col +# 91| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 89| 0: [Parameter] c +# 89| 1: [Parameter] col +# 92| 4: [BlockStmt] {...} +# 93| 0: [ExprStmt] ...; +# 93| 0: [AssignExpr] ... = ... +# 93| 0: [MethodCall] call to method ToUpper +# 93| -1: [TypeAccess] access to type Char +# 93| 0: [ParameterAccess] access to parameter c +# 93| 1: [ParameterAccess] access to parameter c +# 94| 1: [IfStmt] if (...) ... +# 94| 0: [LogicalOrExpr] ... || ... +# 94| 0: [LTExpr] ... < ... +# 94| 0: [CastExpr] (...) ... +# 94| 0: [ParameterAccess] access to parameter c +# 94| 1: [CastExpr] (...) ... +# 94| 0: [CharLiteral] A +# 94| 1: [GTExpr] ... > ... +# 94| 0: [CastExpr] (...) ... +# 94| 0: [ParameterAccess] access to parameter c +# 94| 1: [CastExpr] (...) ... +# 94| 0: [CharLiteral] Z +# 95| 1: [BlockStmt] {...} +# 96| 0: [ThrowStmt] throw ...; +# 96| 0: [ObjectCreation] object creation of type ArgumentException +# 98| 2: [IfStmt] if (...) ... +# 98| 0: [LogicalOrExpr] ... || ... +# 98| 0: [LTExpr] ... < ... +# 98| 0: [ParameterAccess] access to parameter col +# 98| 1: [IntLiteral] 0 +# 98| 1: [GEExpr] ... >= ... +# 98| 0: [ParameterAccess] access to parameter col +# 98| 1: [MemberConstantAccess] access to constant NumCols +# 99| 1: [BlockStmt] {...} +# 100| 0: [ThrowStmt] throw ...; +# 100| 0: [ObjectCreation] object creation of type IndexOutOfRangeException +# 102| 3: [ReturnStmt] return ...; +# 102| 0: [ArrayAccess] access to array element +# 102| -1: [FieldAccess] access to field cells +# 102| 0: [SubExpr] ... - ... +# 102| 0: [CastExpr] (...) ... +# 102| 0: [ParameterAccess] access to parameter c +# 102| 1: [CastExpr] (...) ... +# 102| 0: [CharLiteral] A +# 102| 1: [ParameterAccess] access to parameter col +# 104| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 89| 0: [Parameter] c +# 89| 1: [Parameter] col +# 104| 2: [Parameter] value +# 105| 4: [BlockStmt] {...} +# 106| 0: [ExprStmt] ...; +# 106| 0: [AssignExpr] ... = ... +# 106| 0: [MethodCall] call to method ToUpper +# 106| -1: [TypeAccess] access to type Char +# 106| 0: [ParameterAccess] access to parameter c +# 106| 1: [ParameterAccess] access to parameter c +# 107| 1: [IfStmt] if (...) ... +# 107| 0: [LogicalOrExpr] ... || ... +# 107| 0: [LTExpr] ... < ... +# 107| 0: [CastExpr] (...) ... +# 107| 0: [ParameterAccess] access to parameter c +# 107| 1: [CastExpr] (...) ... +# 107| 0: [CharLiteral] A +# 107| 1: [GTExpr] ... > ... +# 107| 0: [CastExpr] (...) ... +# 107| 0: [ParameterAccess] access to parameter c +# 107| 1: [CastExpr] (...) ... +# 107| 0: [CharLiteral] Z +# 108| 1: [BlockStmt] {...} +# 109| 0: [ThrowStmt] throw ...; +# 109| 0: [ObjectCreation] object creation of type ArgumentException +# 111| 2: [IfStmt] if (...) ... +# 111| 0: [LogicalOrExpr] ... || ... +# 111| 0: [LTExpr] ... < ... +# 111| 0: [ParameterAccess] access to parameter col +# 111| 1: [IntLiteral] 0 +# 111| 1: [GEExpr] ... >= ... +# 111| 0: [ParameterAccess] access to parameter col +# 111| 1: [MemberConstantAccess] access to constant NumCols +# 112| 1: [BlockStmt] {...} +# 113| 0: [ThrowStmt] throw ...; +# 113| 0: [ObjectCreation] object creation of type IndexOutOfRangeException +# 115| 3: [ExprStmt] ...; +# 115| 0: [AssignExpr] ... = ... +# 115| 0: [ParameterAccess] access to parameter value +# 115| 1: [ArrayAccess] access to array element +# 115| -1: [FieldAccess] access to field cells +# 115| 0: [SubExpr] ... - ... +# 115| 0: [CastExpr] (...) ... +# 115| 0: [ParameterAccess] access to parameter c +# 115| 1: [CastExpr] (...) ... +# 115| 0: [CharLiteral] A +# 115| 1: [ParameterAccess] access to parameter col +# 121| 4: [Class] DuplicateIndexerSignatures +# 123| 5: [Indexer] Item +#-----| 1: (Parameters) +# 123| 0: [Parameter] index +# 125| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 123| 0: [Parameter] index +# 125| 4: [BlockStmt] {...} +# 125| 0: [ReturnStmt] return ...; +# 125| 0: [BoolLiteral] false +# 128| 6: [Indexer] Item +#-----| 1: (Parameters) +# 128| 0: [Parameter] c +# 128| 1: [Parameter] col +# 130| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 128| 0: [Parameter] c +# 128| 1: [Parameter] col +# 130| 4: [BlockStmt] {...} +# 130| 0: [ReturnStmt] return ...; +# 130| 0: [IntLiteral] 0 diff --git a/csharp/ql/test/library-tests/indexers/PrintAst.qlref b/csharp/ql/test/library-tests/indexers/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/indexers/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/initializers/PrintAst.expected b/csharp/ql/test/library-tests/initializers/PrintAst.expected new file mode 100644 index 00000000000..b80326a1751 --- /dev/null +++ b/csharp/ql/test/library-tests/initializers/PrintAst.expected @@ -0,0 +1,58 @@ +initializers.cs: +# 3| [Class] S1 +# 5| 5: [Field] P1 +# 6| 6: [Property] P2 +# 6| 3: [Getter] get_P2 +# 6| 4: [Setter] set_P2 +#-----| 2: (Parameters) +# 6| 0: [Parameter] value +# 7| 7: [Property] P3 +# 7| 3: [Setter] set_P3 +#-----| 2: (Parameters) +# 7| 0: [Parameter] value +# 7| 4: [BlockStmt] {...} +# 10| [Class] S2 +#-----| 3: (Base types) +# 10| 1: [Interface] IEnumerable +# 12| 5: [Method] Add +#-----| 2: (Parameters) +# 12| 0: [Parameter] x +# 12| 4: [BlockStmt] {...} +# 13| 6: [Method] Add +#-----| 2: (Parameters) +# 13| 0: [Parameter] x +# 13| 1: [Parameter] y +# 13| 4: [BlockStmt] {...} +# 14| 7: [Method] GetEnumerator +# 14| 4: [BlockStmt] {...} +# 14| 0: [ReturnStmt] return ...; +# 14| 0: [NullLiteral] null +# 17| [Class] Test +# 19| 5: [Method] Main +#-----| 2: (Parameters) +# 19| 0: [Parameter] args +# 20| 4: [BlockStmt] {...} +# 21| 0: [ExprStmt] ...; +# 21| 0: [ObjectCreation] object creation of type S1 +# 21| -1: [ObjectInitializer] { ..., ... } +# 21| 0: [MemberInitializer] ... = ... +# 21| 0: [IntLiteral] 1 +# 21| 1: [FieldAccess] access to field P1 +# 21| 1: [MemberInitializer] ... = ... +# 21| 0: [IntLiteral] 2 +# 21| 1: [PropertyCall] access to property P2 +# 21| 2: [MemberInitializer] ... = ... +# 21| 0: [IntLiteral] 3 +# 21| 1: [PropertyCall] access to property P3 +# 22| 1: [ExprStmt] ...; +# 22| 0: [ObjectCreation] object creation of type S2 +# 22| -1: [CollectionInitializer] { ..., ... } +# 22| 0: [ElementInitializer] call to method Add +# 22| 0: [IntLiteral] 1 +# 22| 1: [ElementInitializer] call to method Add +# 22| 0: [IntLiteral] 2 +# 22| 2: [ElementInitializer] call to method Add +# 22| 0: [IntLiteral] 3 +# 22| 3: [ElementInitializer] call to method Add +# 22| 0: [IntLiteral] 4 +# 22| 1: [IntLiteral] 5 diff --git a/csharp/ql/test/library-tests/initializers/PrintAst.qlref b/csharp/ql/test/library-tests/initializers/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/initializers/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/linq/PrintAst.expected b/csharp/ql/test/library-tests/linq/PrintAst.expected new file mode 100644 index 00000000000..bf38619f4d7 --- /dev/null +++ b/csharp/ql/test/library-tests/linq/PrintAst.expected @@ -0,0 +1,194 @@ +queries.cs: +# 5| [Class] Queries +# 7| 5: [Method] Queries1 +# 8| 4: [BlockStmt] {...} +# 9| 0: [LocalVariableDeclStmt] ... ...; +# 9| 0: [LocalVariableDeclAndInitExpr] IList list1 = ... +# 9| 0: [ObjectCreation] object creation of type List +# 9| -1: [CollectionInitializer] { ..., ... } +# 9| 0: [ElementInitializer] call to method Add +# 9| 0: [IntLiteral] 1 +# 9| 1: [ElementInitializer] call to method Add +# 9| 0: [IntLiteral] 2 +# 9| 2: [ElementInitializer] call to method Add +# 9| 0: [IntLiteral] 3 +# 9| 1: [LocalVariableAccess] access to local variable list1 +# 10| 1: [LocalVariableDeclStmt] ... ...; +# 10| 0: [LocalVariableDeclAndInitExpr] IList> list2 = ... +# 10| 0: [ObjectCreation] object creation of type List> +# 10| -1: [CollectionInitializer] { ..., ... } +# 10| 0: [ElementInitializer] call to method Add +# 10| 0: [LocalVariableAccess] access to local variable list1 +# 10| 1: [ElementInitializer] call to method Add +# 10| 0: [LocalVariableAccess] access to local variable list1 +# 10| 1: [LocalVariableAccess] access to local variable list2 +# 12| 2: [LocalVariableDeclStmt] ... ...; +# 12| 0: [LocalVariableDeclAndInitExpr] IEnumerable list3 = ... +# 16| 0: [MethodCall] call to method Select +# 15| 0: [MethodCall] call to method OrderBy +# 14| 0: [MethodCall] call to method Where +# 13| 0: [LocalVariableDeclAndInitExpr] Int32 a = ... +# 13| 0: [LocalVariableAccess] access to local variable list1 +# 13| 1: [LocalVariableAccess] access to local variable a +# 14| 1: [LogicalOrExpr] ... || ... +# 14| 0: [EQExpr] ... == ... +# 14| 0: [LocalVariableAccess] access to local variable a +# 14| 1: [IntLiteral] 2 +# 14| 1: [EQExpr] ... == ... +# 14| 0: [LocalVariableAccess] access to local variable a +# 14| 1: [IntLiteral] 3 +# 15| 1: [LocalVariableAccess] access to local variable a +# 16| 1: [AddExpr] ... + ... +# 16| 0: [LocalVariableAccess] access to local variable a +# 16| 1: [IntLiteral] 1 +# 12| 1: [LocalVariableAccess] access to local variable list3 +# 18| 3: [LocalVariableDeclStmt] ... ...; +# 18| 0: [LocalVariableDeclAndInitExpr] IEnumerable list4 = ... +# 18| 0: [MethodCall] call to method Select +# 18| -1: [MethodCall] call to method OrderBy +# 18| -1: [MethodCall] call to method Where +# 18| -1: [LocalVariableAccess] access to local variable list1 +# 19| 0: [LambdaExpr] (...) => ... +#-----| 2: (Parameters) +# 19| 0: [Parameter] a +# 19| 4: [LogicalOrExpr] ... || ... +# 19| 0: [EQExpr] ... == ... +# 19| 0: [ParameterAccess] access to parameter a +# 19| 1: [IntLiteral] 2 +# 19| 1: [EQExpr] ... == ... +# 19| 0: [ParameterAccess] access to parameter a +# 19| 1: [IntLiteral] 3 +# 20| 0: [LambdaExpr] (...) => ... +#-----| 2: (Parameters) +# 20| 0: [Parameter] a +# 20| 4: [ParameterAccess] access to parameter a +# 21| 0: [LambdaExpr] (...) => ... +#-----| 2: (Parameters) +# 21| 0: [Parameter] a +# 21| 4: [AddExpr] ... + ... +# 21| 0: [ParameterAccess] access to parameter a +# 21| 1: [IntLiteral] 1 +# 18| 1: [LocalVariableAccess] access to local variable list4 +# 23| 4: [LocalVariableDeclStmt] ... ...; +# 23| 0: [LocalVariableDeclAndInitExpr] IEnumerable list5 = ... +# 28| 0: [MethodCall] call to method +# 27| 0: [MethodCall] call to method Join +# 26| 0: [MethodCall] call to method Select +# 25| 0: [MethodCall] call to method SelectMany +# 24| 0: [LocalVariableDeclAndInitExpr] IList a = ... +# 24| 0: [LocalVariableAccess] access to local variable list2 +# 24| 1: [LocalVariableAccess] access to local variable a +# 25| 1: [LocalVariableDeclAndInitExpr] IList b = ... +# 25| 0: [LocalVariableAccess] access to local variable a +# 25| 1: [LocalVariableAccess] access to local variable b +# 25| 2: [LocalVariableAccess] access to local variable a +# 26| 1: [LocalVariableDeclAndInitExpr] Int32 next = ... +# 26| 0: [AddExpr] ... + ... +# 26| 0: [LocalVariableAccess] access to local variable b +# 26| 1: [IntLiteral] 1 +# 26| 1: [LocalVariableAccess] access to local variable next +# 26| 2: [AddExpr] ... + ... +# 26| 0: [LocalVariableAccess] access to local variable b +# 26| 1: [IntLiteral] 1 +# 27| 1: [LocalVariableDeclAndInitExpr] IList c = ... +# 27| 0: [LocalVariableAccess] access to local variable list1 +# 27| 1: [LocalVariableAccess] access to local variable c +# 27| 2: [LocalVariableAccess] access to local variable list1 +# 27| 3: [LocalVariableAccess] access to local variable next +# 27| 4: [LocalVariableAccess] access to local variable c +# 28| 1: [IntLiteral] 1 +# 23| 1: [LocalVariableAccess] access to local variable list5 +# 30| 5: [LocalVariableDeclStmt] ... ...; +# 30| 0: [LocalVariableDeclAndInitExpr] IEnumerable> list6 = ... +# 35| 0: [MethodCall] call to method GroupBy +# 34| 0: [MethodCall] call to method OrderByDescending +# 33| 0: [MethodCall] call to method Select +# 32| 0: [MethodCall] call to method SelectMany +# 31| 0: [LocalVariableDeclAndInitExpr] IList a = ... +# 31| 0: [LocalVariableAccess] access to local variable list2 +# 31| 1: [LocalVariableAccess] access to local variable a +# 32| 1: [LocalVariableDeclAndInitExpr] IList b = ... +# 32| 0: [LocalVariableAccess] access to local variable a +# 32| 1: [LocalVariableAccess] access to local variable b +# 32| 2: [LocalVariableAccess] access to local variable a +# 33| 1: [LocalVariableDeclAndInitExpr] Int32 next = ... +# 33| 0: [AddExpr] ... + ... +# 33| 0: [LocalVariableAccess] access to local variable b +# 33| 1: [IntLiteral] 1 +# 33| 1: [LocalVariableAccess] access to local variable next +# 33| 2: [AddExpr] ... + ... +# 33| 0: [LocalVariableAccess] access to local variable b +# 33| 1: [IntLiteral] 1 +# 34| 1: [MulExpr] ... * ... +# 34| 0: [LocalVariableAccess] access to local variable next +# 34| 1: [IntLiteral] 2 +# 35| 1: [LocalVariableAccess] access to local variable b +# 35| 2: [LocalVariableAccess] access to local variable next +# 30| 1: [LocalVariableAccess] access to local variable list6 +# 37| 6: [LocalVariableDeclStmt] ... ...; +# 37| 0: [LocalVariableDeclAndInitExpr] B list7 = ... +# 37| 0: [ObjectCreation] object creation of type B +# 37| 1: [LocalVariableAccess] access to local variable list7 +# 39| 7: [LocalVariableDeclStmt] ... ...; +# 39| 0: [LocalVariableDeclAndInitExpr] IEnumerable list8 = ... +# 41| 0: [MethodCall] call to method Select +# 40| 0: [LocalVariableDeclAndInitExpr] Object a = ... +# 40| 0: [LocalVariableAccess] access to local variable list7 +# 40| 1: [LocalVariableAccess] access to local variable a +# 41| 1: [LocalVariableAccess] access to local variable a +# 39| 1: [LocalVariableAccess] access to local variable list8 +# 43| 8: [LocalVariableDeclStmt] ... ...; +# 43| 0: [LocalVariableDeclAndInitExpr] C list9 = ... +# 43| 0: [ObjectCreation] object creation of type C +# 43| 1: [LocalVariableAccess] access to local variable list9 +# 45| 9: [LocalVariableDeclStmt] ... ...; +# 45| 0: [LocalVariableDeclAndInitExpr] IEnumerable list10 = ... +# 47| 0: [MethodCall] call to method Select +# 46| 0: [LocalVariableDeclAndInitExpr] Int32 a = ... +# 46| 0: [LocalVariableAccess] access to local variable list9 +# 46| 1: [LocalVariableAccess] access to local variable a +# 47| 1: [LocalVariableAccess] access to local variable a +# 45| 1: [LocalVariableAccess] access to local variable list10 +# 49| 10: [LocalVariableDeclStmt] ... ...; +# 49| 0: [LocalVariableDeclAndInitExpr] IEnumerable list11 = ... +# 51| 0: [MethodCall] call to method Select +# 50| 0: [LocalVariableDeclAndInitExpr] String a = ... +# 50| 0: [LocalVariableAccess] access to local variable list7 +# 50| 1: [LocalVariableAccess] access to local variable a +# 51| 1: [LocalVariableAccess] access to local variable a +# 49| 1: [LocalVariableAccess] access to local variable list11 +# 53| 11: [LocalVariableDeclStmt] ... ...; +# 53| 0: [LocalVariableDeclAndInitExpr] IEnumerable<(Int32,IEnumerable>)> list12 = ... +# 56| 0: [MethodCall] call to method +# 55| 0: [MethodCall] call to method GroupJoin +# 54| 0: [LocalVariableDeclAndInitExpr] Int32 a = ... +# 54| 0: [LocalVariableAccess] access to local variable list1 +# 54| 1: [LocalVariableAccess] access to local variable a +# 55| 1: [LocalVariableDeclAndInitExpr] IList> c = ... +# 55| 0: [LocalVariableAccess] access to local variable list2 +# 55| 1: [LocalVariableAccess] access to local variable c +# 55| 2: [LocalVariableAccess] access to local variable list2 +# 55| 3: [LocalVariableAccess] access to local variable a +# 55| 4: [IndexerCall] access to indexer +# 55| -1: [LocalVariableAccess] access to local variable c +# 55| 0: [IntLiteral] 0 +# 55| 5: [LocalVariableDeclAndInitExpr] IList> d = ... +# 55| 0: [LocalVariableAccess] access to local variable list2 +# 55| 1: [LocalVariableAccess] access to local variable d +# 56| 1: [TupleExpr] (..., ...) +# 56| 0: [LocalVariableAccess] access to local variable a +# 56| 1: [LocalVariableAccess] access to local variable d +# 53| 1: [LocalVariableAccess] access to local variable list12 +# 59| 6: [Class] A +#-----| 3: (Base types) +# 59| 1: [Interface] IEnumerable +# 61| 5: [Method] GetEnumerator +# 62| 4: [BlockStmt] {...} +# 63| 0: [ThrowStmt] throw ...; +# 63| 0: [ObjectCreation] object creation of type NotImplementedException +# 67| 7: [Class] B +#-----| 3: (Base types) +# 67| 0: [Class] A +# 69| 8: [Class] C +#-----| 3: (Base types) +# 69| 0: [Class] List diff --git a/csharp/ql/test/library-tests/linq/PrintAst.qlref b/csharp/ql/test/library-tests/linq/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/linq/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/members/PrintAst.expected b/csharp/ql/test/library-tests/members/PrintAst.expected new file mode 100644 index 00000000000..bcf009056f0 --- /dev/null +++ b/csharp/ql/test/library-tests/members/PrintAst.expected @@ -0,0 +1,184 @@ +Members.cs: +# 1| [NamespaceDeclaration] namespace ... { ... } +# 3| 1: [DelegateType] EventHandler +#-----| 2: (Parameters) +# 3| 0: [Parameter] sender +# 3| 1: [Parameter] e +# 6| 2: [Class] Class +# 9| 5: [Class] NestedClass +# 12| 5: [Method] Method +#-----| 1: (Type parameters) +# 12| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 12| 0: [Parameter] t +# 12| 4: [MethodCall] call to method ToString +# 12| -1: [ParameterAccess] access to parameter t +# 14| 6: [Indexer] Item +#-----| 1: (Parameters) +# 14| 0: [Parameter] i +# 14| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 14| 0: [Parameter] i +# 14| 4: [MethodCall] call to method ToString +# 14| -1: [ParameterAccess] access to parameter i +# 14| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 14| 0: [Parameter] i +# 14| 1: [Parameter] value +# 14| 4: [BlockStmt] {...} +# 16| 7: [Field] Field +# 18| 8: [IndexerProperty] Prop +# 18| 3: [Getter] get_Prop +# 18| 4: [Setter] set_Prop +#-----| 2: (Parameters) +# 18| 0: [Parameter] value +# 20| 9: [Event] Event +# 20| 3: [AddEventAccessor] add_Event +#-----| 2: (Parameters) +# 20| 0: [Parameter] value +# 20| 3: [RemoveEventAccessor] remove_Event +#-----| 2: (Parameters) +# 20| 0: [Parameter] value +# 24| 6: [Method] Method +# 24| 4: [BlockStmt] {...} +# 26| 7: [Indexer] Item +#-----| 1: (Parameters) +# 26| 0: [Parameter] i +# 26| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 26| 0: [Parameter] i +# 26| 4: [MethodCall] call to method ToString +# 26| -1: [ParameterAccess] access to parameter i +# 26| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 26| 0: [Parameter] i +# 26| 1: [Parameter] value +# 26| 4: [BlockStmt] {...} +# 28| 8: [Field] Field +# 30| 9: [IndexerProperty] Prop +# 30| 3: [Getter] get_Prop +# 30| 4: [Setter] set_Prop +#-----| 2: (Parameters) +# 30| 0: [Parameter] value +# 32| 10: [Event] Event +# 32| 3: [AddEventAccessor] add_Event +#-----| 2: (Parameters) +# 32| 0: [Parameter] value +# 32| 3: [RemoveEventAccessor] remove_Event +#-----| 2: (Parameters) +# 32| 0: [Parameter] value +# 35| 3: [Class] Class2 +# 37| 5: [Class] NestedClass2 +# 39| 5: [Method] Method +#-----| 1: (Type parameters) +# 39| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 39| 0: [Parameter] t +# 39| 4: [MethodCall] call to method ToString +# 39| -1: [ParameterAccess] access to parameter t +# 40| 6: [Indexer] Item +#-----| 1: (Parameters) +# 40| 0: [Parameter] i +# 40| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 40| 0: [Parameter] i +# 40| 4: [MethodCall] call to method ToString +# 40| -1: [ParameterAccess] access to parameter i +# 40| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 40| 0: [Parameter] i +# 40| 1: [Parameter] value +# 40| 4: [BlockStmt] {...} +# 41| 7: [Field] Field +# 42| 8: [IndexerProperty] Prop +# 42| 3: [Getter] get_Prop +# 42| 4: [Setter] set_Prop +#-----| 2: (Parameters) +# 42| 0: [Parameter] value +# 43| 9: [Event] Event +# 43| 3: [AddEventAccessor] add_Event +#-----| 2: (Parameters) +# 43| 0: [Parameter] value +# 43| 3: [RemoveEventAccessor] remove_Event +#-----| 2: (Parameters) +# 43| 0: [Parameter] value +# 46| 6: [Method] Method +# 46| 4: [BlockStmt] {...} +# 47| 7: [Indexer] Item +#-----| 1: (Parameters) +# 47| 0: [Parameter] i +# 47| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 47| 0: [Parameter] i +# 47| 4: [MethodCall] call to method ToString +# 47| -1: [ParameterAccess] access to parameter i +# 47| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 47| 0: [Parameter] i +# 47| 1: [Parameter] value +# 47| 4: [BlockStmt] {...} +# 48| 8: [Field] Field +# 49| 9: [IndexerProperty] Prop +# 49| 3: [Getter] get_Prop +# 49| 4: [Setter] set_Prop +#-----| 2: (Parameters) +# 49| 0: [Parameter] value +# 50| 10: [Event] Event +# 50| 3: [AddEventAccessor] add_Event +#-----| 2: (Parameters) +# 50| 0: [Parameter] value +# 50| 3: [RemoveEventAccessor] remove_Event +#-----| 2: (Parameters) +# 50| 0: [Parameter] value +# 54| 4: [Interface] Interface +# 56| 4: [Method] Method +# 57| 5: [Indexer] Item +#-----| 1: (Parameters) +# 57| 0: [Parameter] i +# 57| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 57| 0: [Parameter] i +# 57| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 57| 0: [Parameter] i +# 57| 1: [Parameter] value +# 58| 6: [IndexerProperty] Prop +# 58| 3: [Getter] get_Prop +# 58| 4: [Setter] set_Prop +#-----| 2: (Parameters) +# 58| 0: [Parameter] value +# 59| 7: [Event] Event +# 59| 3: [AddEventAccessor] add_Event +#-----| 2: (Parameters) +# 59| 0: [Parameter] value +# 59| 3: [RemoveEventAccessor] remove_Event +#-----| 2: (Parameters) +# 59| 0: [Parameter] value +# 62| 5: [Interface] Interface2 +# 64| 4: [Method] Method +# 65| 5: [Indexer] Item +#-----| 1: (Parameters) +# 65| 0: [Parameter] i +# 65| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 65| 0: [Parameter] i +# 65| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 65| 0: [Parameter] i +# 65| 1: [Parameter] value +# 66| 6: [IndexerProperty] Prop +# 66| 3: [Getter] get_Prop +# 66| 4: [Setter] set_Prop +#-----| 2: (Parameters) +# 66| 0: [Parameter] value +# 67| 7: [Event] Event +# 67| 3: [AddEventAccessor] add_Event +#-----| 2: (Parameters) +# 67| 0: [Parameter] value +# 67| 3: [RemoveEventAccessor] remove_Event +#-----| 2: (Parameters) +# 67| 0: [Parameter] value +# 71| 6: [Enum] Enum +# 73| 7: [Enum] Enum2 +# 76| 8: [Struct] Struct +# 78| 9: [Struct] Struct2 diff --git a/csharp/ql/test/library-tests/members/PrintAst.qlref b/csharp/ql/test/library-tests/members/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/members/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/methods/PrintAst.expected b/csharp/ql/test/library-tests/methods/PrintAst.expected new file mode 100644 index 00000000000..f1fcd161bb3 --- /dev/null +++ b/csharp/ql/test/library-tests/methods/PrintAst.expected @@ -0,0 +1,367 @@ +methods.cs: +# 3| [NamespaceDeclaration] namespace ... { ... } +# 6| 1: [Class] TestRef +# 9| 5: [Method] Swap +#-----| 2: (Parameters) +# 9| 0: [Parameter] x +# 9| 1: [Parameter] y +# 10| 4: [BlockStmt] {...} +# 11| 0: [LocalVariableDeclStmt] ... ...; +# 11| 0: [LocalVariableDeclAndInitExpr] Int32 temp = ... +# 11| 0: [ParameterAccess] access to parameter x +# 11| 1: [LocalVariableAccess] access to local variable temp +# 12| 1: [ExprStmt] ...; +# 12| 0: [AssignExpr] ... = ... +# 12| 0: [ParameterAccess] access to parameter y +# 12| 1: [ParameterAccess] access to parameter x +# 13| 2: [ExprStmt] ...; +# 13| 0: [AssignExpr] ... = ... +# 13| 0: [LocalVariableAccess] access to local variable temp +# 13| 1: [ParameterAccess] access to parameter y +# 16| 6: [Method] Main +# 17| 4: [BlockStmt] {...} +# 18| 0: [LocalVariableDeclStmt] ... ...; +# 18| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 18| 0: [IntLiteral] 1 +# 18| 1: [LocalVariableAccess] access to local variable i +# 18| 1: [LocalVariableDeclAndInitExpr] Int32 j = ... +# 18| 0: [IntLiteral] 2 +# 18| 1: [LocalVariableAccess] access to local variable j +# 19| 1: [ExprStmt] ...; +# 19| 0: [MethodCall] call to method Swap +# 19| 0: [LocalVariableAccess] access to local variable i +# 19| 1: [LocalVariableAccess] access to local variable j +# 20| 2: [ExprStmt] ...; +# 20| 0: [MethodCall] call to method WriteLine +# 20| -1: [TypeAccess] access to type Console +# 20| 0: [StringLiteral] "{0} {1}" +# 20| 1: [CastExpr] (...) ... +# 20| 0: [LocalVariableAccess] access to local variable i +# 20| 2: [CastExpr] (...) ... +# 20| 0: [LocalVariableAccess] access to local variable j +# 21| 3: [ExprStmt] ...; +# 21| 0: [MethodCall] call to method WriteLine +# 21| -1: [TypeAccess] access to type Console +# 21| 0: [StringLiteral] "{0} {1}" +# 21| 1: [CastExpr] (...) ... +# 21| 0: [LocalVariableAccess] access to local variable i +# 21| 2: [CastExpr] (...) ... +# 21| 0: [LocalVariableAccess] access to local variable j +# 25| 2: [Class] TestOut +# 28| 5: [Method] Divide +#-----| 2: (Parameters) +# 28| 0: [Parameter] x +# 28| 1: [Parameter] y +# 28| 2: [Parameter] result +# 28| 3: [Parameter] remainder +# 29| 4: [BlockStmt] {...} +# 30| 0: [ExprStmt] ...; +# 30| 0: [AssignExpr] ... = ... +# 30| 0: [DivExpr] ... / ... +# 30| 0: [ParameterAccess] access to parameter x +# 30| 1: [ParameterAccess] access to parameter y +# 30| 1: [ParameterAccess] access to parameter result +# 31| 1: [ExprStmt] ...; +# 31| 0: [AssignExpr] ... = ... +# 31| 0: [RemExpr] ... % ... +# 31| 0: [ParameterAccess] access to parameter x +# 31| 1: [ParameterAccess] access to parameter y +# 31| 1: [ParameterAccess] access to parameter remainder +# 34| 6: [Method] Main +# 35| 4: [BlockStmt] {...} +# 36| 0: [LocalVariableDeclStmt] ... ...; +# 36| 0: [LocalVariableDeclExpr] Int32 res +# 36| 1: [LocalVariableDeclExpr] Int32 rem +# 37| 1: [ExprStmt] ...; +# 37| 0: [MethodCall] call to method Divide +# 37| 0: [IntLiteral] 10 +# 37| 1: [IntLiteral] 3 +# 37| 2: [LocalVariableAccess] access to local variable res +# 37| 3: [LocalVariableAccess] access to local variable rem +# 38| 2: [ExprStmt] ...; +# 38| 0: [MethodCall] call to method WriteLine +# 38| -1: [TypeAccess] access to type Console +# 38| 0: [StringLiteral] "{0} {1}" +# 38| 1: [CastExpr] (...) ... +# 38| 0: [LocalVariableAccess] access to local variable res +# 38| 2: [CastExpr] (...) ... +# 38| 0: [LocalVariableAccess] access to local variable rem +# 42| 3: [Class] Console +# 45| 5: [Method] Write +#-----| 2: (Parameters) +# 45| 0: [Parameter] fmt +# 45| 1: [Parameter] args +# 45| 4: [BlockStmt] {...} +# 46| 6: [Method] WriteLine +#-----| 2: (Parameters) +# 46| 0: [Parameter] fmt +# 46| 1: [Parameter] args +# 46| 4: [BlockStmt] {...} +# 49| 4: [Class] TestOverloading +# 52| 5: [Method] F +# 53| 4: [BlockStmt] {...} +# 54| 0: [ExprStmt] ...; +# 54| 0: [MethodCall] call to method WriteLine +# 54| -1: [TypeAccess] access to type Console +# 54| 0: [StringLiteral] "F()" +# 57| 6: [Method] F +#-----| 2: (Parameters) +# 57| 0: [Parameter] x +# 58| 4: [BlockStmt] {...} +# 59| 0: [ExprStmt] ...; +# 59| 0: [MethodCall] call to method WriteLine +# 59| -1: [TypeAccess] access to type Console +# 59| 0: [StringLiteral] "F(object)" +# 62| 7: [Method] F +#-----| 2: (Parameters) +# 62| 0: [Parameter] x +# 63| 4: [BlockStmt] {...} +# 64| 0: [ExprStmt] ...; +# 64| 0: [MethodCall] call to method WriteLine +# 64| -1: [TypeAccess] access to type Console +# 64| 0: [StringLiteral] "F(int)" +# 67| 8: [Method] F +#-----| 2: (Parameters) +# 67| 0: [Parameter] x +# 68| 4: [BlockStmt] {...} +# 69| 0: [ExprStmt] ...; +# 69| 0: [MethodCall] call to method WriteLine +# 69| -1: [TypeAccess] access to type Console +# 69| 0: [StringLiteral] "F(double)" +# 72| 9: [Method] F +#-----| 1: (Type parameters) +# 72| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 72| 0: [Parameter] x +# 73| 4: [BlockStmt] {...} +# 74| 0: [ExprStmt] ...; +# 74| 0: [MethodCall] call to method WriteLine +# 74| -1: [TypeAccess] access to type Console +# 74| 0: [StringLiteral] "F(T)" +# 77| 12: [Method] F +#-----| 2: (Parameters) +# 77| 0: [Parameter] x +# 77| 1: [Parameter] y +# 78| 4: [BlockStmt] {...} +# 79| 0: [ExprStmt] ...; +# 79| 0: [MethodCall] call to method WriteLine +# 79| -1: [TypeAccess] access to type Console +# 79| 0: [StringLiteral] "F(double, double)" +# 82| 13: [Method] Main +# 83| 4: [BlockStmt] {...} +# 84| 0: [ExprStmt] ...; +# 84| 0: [MethodCall] call to method F +# 85| 1: [ExprStmt] ...; +# 85| 0: [MethodCall] call to method F +# 85| 0: [IntLiteral] 1 +# 86| 2: [ExprStmt] ...; +# 86| 0: [MethodCall] call to method F +# 86| 0: [DoubleLiteral] 1 +# 87| 3: [ExprStmt] ...; +# 87| 0: [MethodCall] call to method F +# 87| 0: [StringLiteral] "abc" +# 88| 4: [ExprStmt] ...; +# 88| 0: [MethodCall] call to method F +# 88| 0: [CastExpr] (...) ... +# 88| 0: [IntLiteral] 1 +# 88| 1: [TypeAccess] access to type Double +# 89| 5: [ExprStmt] ...; +# 89| 0: [MethodCall] call to method F +# 89| 0: [CastExpr] (...) ... +# 89| 0: [IntLiteral] 1 +# 89| 1: [TypeAccess] access to type Object +# 90| 6: [ExprStmt] ...; +# 90| 0: [MethodCall] call to method F +# 90| 0: [IntLiteral] 1 +# 91| 7: [ExprStmt] ...; +# 91| 0: [MethodCall] call to method F +# 91| 0: [CastExpr] (...) ... +# 91| 0: [IntLiteral] 1 +# 91| 1: [CastExpr] (...) ... +# 91| 0: [IntLiteral] 1 +# 96| 5: [Class] Extensions +# 99| 4: [ExtensionMethod] ToInt32 +#-----| 2: (Parameters) +# 99| 0: [Parameter] s +# 100| 4: [BlockStmt] {...} +# 101| 0: [ReturnStmt] return ...; +# 101| 0: [MethodCall] call to method Parse +# 101| -1: [TypeAccess] access to type Int32 +# 101| 0: [ParameterAccess] access to parameter s +# 104| 5: [ExtensionMethod] ToBool +#-----| 2: (Parameters) +# 104| 0: [Parameter] s +# 104| 1: [Parameter] f +# 105| 4: [BlockStmt] {...} +# 106| 0: [ReturnStmt] return ...; +# 106| 0: [DelegateCall] delegate call +# 106| -1: [ParameterAccess] access to parameter f +# 106| 0: [ParameterAccess] access to parameter s +# 109| 6: [ExtensionMethod] Slice +#-----| 1: (Type parameters) +# 109| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 109| 0: [Parameter] source +# 109| 1: [Parameter] index +# 109| 2: [Parameter] count +# 110| 4: [BlockStmt] {...} +# 111| 0: [IfStmt] if (...) ... +# 111| 0: [LogicalOrExpr] ... || ... +# 111| 0: [LogicalOrExpr] ... || ... +# 111| 0: [LTExpr] ... < ... +# 111| 0: [ParameterAccess] access to parameter index +# 111| 1: [IntLiteral] 0 +# 111| 1: [LTExpr] ... < ... +# 111| 0: [ParameterAccess] access to parameter count +# 111| 1: [IntLiteral] 0 +# 111| 1: [LTExpr] ... < ... +# 111| 0: [SubExpr] ... - ... +# 111| 0: [PropertyCall] access to property Length +# 111| -1: [ParameterAccess] access to parameter source +# 111| 1: [ParameterAccess] access to parameter index +# 111| 1: [ParameterAccess] access to parameter count +# 112| 1: [ThrowStmt] throw ...; +# 112| 0: [ObjectCreation] object creation of type ArgumentException +# 113| 1: [LocalVariableDeclStmt] ... ...; +# 113| 0: [LocalVariableDeclAndInitExpr] T[] result = ... +# 113| 0: [ArrayCreation] array creation of type T[] +# 113| 0: [ParameterAccess] access to parameter count +# 113| 1: [LocalVariableAccess] access to local variable result +# 114| 2: [ExprStmt] ...; +# 114| 0: [MethodCall] call to method Copy +# 114| -1: [TypeAccess] access to type Array +# 114| 0: [ParameterAccess] access to parameter source +# 114| 1: [ParameterAccess] access to parameter index +# 114| 2: [LocalVariableAccess] access to local variable result +# 114| 3: [IntLiteral] 0 +# 114| 4: [ParameterAccess] access to parameter count +# 115| 3: [ReturnStmt] return ...; +# 115| 0: [LocalVariableAccess] access to local variable result +# 118| 8: [Method] CallToInt32 +# 118| 4: [MethodCall] call to method ToInt32 +# 118| 0: [StringLiteral] "0" +# 121| 6: [Class] TestExtensions +# 124| 4: [Method] Main +# 125| 4: [BlockStmt] {...} +# 126| 0: [LocalVariableDeclStmt] ... ...; +# 126| 0: [LocalVariableDeclAndInitExpr] String[] strings = ... +# 126| 0: [ArrayCreation] array creation of type String[] +# 126| -1: [ArrayInitializer] { ..., ... } +# 126| 0: [StringLiteral] "1" +# 126| 1: [StringLiteral] "22" +# 126| 2: [StringLiteral] "333" +# 126| 3: [StringLiteral] "4444" +# 126| 1: [LocalVariableAccess] access to local variable strings +# 127| 1: [ForeachStmt] foreach (... ... in ...) ... +# 127| 0: [LocalVariableDeclExpr] String s +# 127| 1: [MethodCall] call to method Slice +# 127| -1: [LocalVariableAccess] access to local variable strings +# 127| 0: [IntLiteral] 1 +# 127| 1: [IntLiteral] 2 +# 128| 2: [BlockStmt] {...} +# 129| 0: [ExprStmt] ...; +# 129| 0: [MethodCall] call to method WriteLine +# 129| -1: [TypeAccess] access to type Console +# 129| 0: [MethodCall] call to method ToInt32 +# 129| -1: [LocalVariableAccess] access to local variable s +# 132| 2: [ExprStmt] ...; +# 132| 0: [MethodCall] call to method ToInt32 +# 132| -1: [TypeAccess] access to type Extensions +# 132| 0: [StringLiteral] "" +# 134| 3: [ExprStmt] ...; +# 134| 0: [MethodCall] call to method ToBool +# 134| -1: [TypeAccess] access to type Extensions +# 134| 0: [StringLiteral] "true" +# 134| 1: [ImplicitDelegateCreation] delegate creation of type Func +# 134| 0: [MethodAccess] access to method Parse +# 134| -1: [TypeAccess] access to type Boolean +# 139| 7: [Class] TestDefaultParameters +# 141| 4: [Method] Method1 +#-----| 2: (Parameters) +# 141| 0: [Parameter] x +# 141| 1: [Parameter] y +# 142| 4: [BlockStmt] {...} +# 145| 5: [Method] Method2 +#-----| 2: (Parameters) +# 145| 0: [Parameter] a +# 145| 1: [Parameter] b +# 145| 2: [Parameter] c +# 145| 1: [IntLiteral] 1 +# 145| 3: [Parameter] d +# 145| 1: [IntLiteral] 2 +# 145| 4: [Parameter] e +# 145| 1: [AddExpr] ... + ... +# 145| 0: [StringLiteral] "a" +# 145| 1: [StringLiteral] "b" +# 146| 4: [BlockStmt] {...} +# 149| 6: [InstanceConstructor] TestDefaultParameters +#-----| 2: (Parameters) +# 149| 0: [Parameter] x +# 150| 4: [BlockStmt] {...} +# 153| 7: [InstanceConstructor] TestDefaultParameters +#-----| 2: (Parameters) +# 153| 0: [Parameter] x +# 153| 1: [StringLiteral] "abc" +# 153| 1: [Parameter] y +# 153| 1: [ObjectCreation] object creation of type Double +# 154| 4: [BlockStmt] {...} +# 157| 8: [DelegateType] Del +#-----| 2: (Parameters) +# 157| 0: [Parameter] a +# 157| 1: [Parameter] b +# 157| 1: [IntLiteral] 12 +# 157| 2: [Parameter] c +# 157| 1: [ObjectCreation] object creation of type Double +# 159| 9: [Indexer] Item +#-----| 1: (Parameters) +# 159| 0: [Parameter] x +# 159| 1: [Parameter] y +# 159| 1: [IntLiteral] 0 +# 161| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 159| 0: [Parameter] x +# 159| 1: [Parameter] y +# 159| 1: [IntLiteral] 0 +# 161| 4: [BlockStmt] {...} +# 161| 0: [ReturnStmt] return ...; +# 161| 0: [AddExpr] ... + ... +# 161| 0: [ParameterAccess] access to parameter x +# 161| 1: [ParameterAccess] access to parameter y +# 162| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 159| 0: [Parameter] x +# 159| 1: [Parameter] y +# 159| 1: [IntLiteral] 0 +# 162| 2: [Parameter] value +# 162| 4: [BlockStmt] {...} +# 166| 8: [Class] TestDefaultExtensionParameters +# 168| 4: [ExtensionMethod] Plus +#-----| 2: (Parameters) +# 168| 0: [Parameter] left +# 168| 1: [Parameter] right +# 168| 1: [IntLiteral] 0 +# 169| 4: [BlockStmt] {...} +# 170| 0: [ReturnStmt] return ...; +# 170| 0: [AddExpr] ... + ... +# 170| 0: [ParameterAccess] access to parameter left +# 170| 1: [ParameterAccess] access to parameter right +# 173| 5: [ExtensionMethod] SkipTwo +#-----| 1: (Type parameters) +# 173| 0: [TypeParameter] T +#-----| 2: (Parameters) +# 173| 0: [Parameter] list +# 173| 1: [Parameter] i +# 173| 1: [IntLiteral] 1 +# 174| 4: [BlockStmt] {...} +# 175| 0: [ReturnStmt] return ...; +# 175| 0: [ParameterAccess] access to parameter list +# 178| 7: [ExtensionMethod] SkipTwoInt +#-----| 2: (Parameters) +# 178| 0: [Parameter] list +# 178| 1: [Parameter] i +# 178| 1: [IntLiteral] 1 +# 179| 4: [BlockStmt] {...} +# 180| 0: [ReturnStmt] return ...; +# 180| 0: [MethodCall] call to method SkipTwo +# 180| -1: [ParameterAccess] access to parameter list +# 180| 0: [ParameterAccess] access to parameter i diff --git a/csharp/ql/test/library-tests/methods/PrintAst.qlref b/csharp/ql/test/library-tests/methods/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/methods/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/namespaces/PrintAst.expected b/csharp/ql/test/library-tests/namespaces/PrintAst.expected new file mode 100644 index 00000000000..8025fdf4553 --- /dev/null +++ b/csharp/ql/test/library-tests/namespaces/PrintAst.expected @@ -0,0 +1,37 @@ +namespaces.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 8| 1: [Class] A +# 9| 2: [Class] B +# 13| [NamespaceDeclaration] namespace ... { ... } +# 16| 1: [NamespaceDeclaration] namespace ... { ... } +# 19| 1: [Class] A +# 20| 2: [Class] B +# 26| [NamespaceDeclaration] namespace ... { ... } +# 29| 1: [Class] A +# 33| [NamespaceDeclaration] namespace ... { ... } +# 36| 1: [Class] B +# 38| 2: [Struct] S +# 40| 3: [Interface] I +# 44| [NamespaceDeclaration] namespace ... { ... } +# 50| [NamespaceDeclaration] namespace ... { ... } +# 53| 1: [Class] A +# 57| [NamespaceDeclaration] namespace ... { ... } +# 64| 1: [Class] B +#-----| 3: (Base types) +# 64| 0: [Class] A +# 66| 2: [Class] C +#-----| 3: (Base types) +# 66| 0: [Class] A +# 70| [NamespaceDeclaration] namespace ... { ... } +# 73| 1: [Class] A<> +#-----| 1: (Type parameters) +# 73| 0: [TypeParameter] T +# 76| 5: [Class] B +# 80| 2: [Class] A +# 84| [NamespaceDeclaration] namespace ... { ... } +# 91| [NamespaceDeclaration] namespace ... { ... } +# 94| 1: [Class] A +# 97| [NamespaceDeclaration] namespace ... { ... } +# 102| 1: [Class] B +#-----| 3: (Base types) +# 102| 0: [Class] A diff --git a/csharp/ql/test/library-tests/namespaces/PrintAst.qlref b/csharp/ql/test/library-tests/namespaces/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/namespaces/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/nestedtypes/PrintAst.expected b/csharp/ql/test/library-tests/nestedtypes/PrintAst.expected new file mode 100644 index 00000000000..275afe9a2bc --- /dev/null +++ b/csharp/ql/test/library-tests/nestedtypes/PrintAst.expected @@ -0,0 +1,77 @@ +nestedtypes.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 8| 1: [Class] Base +# 11| 5: [Struct] S +# 13| 6: [Interface] I +# 15| 7: [DelegateType] MyDelegate +#-----| 2: (Parameters) +# 15| 0: [Parameter] s +# 17| 8: [Method] F +# 18| 4: [BlockStmt] {...} +# 19| 0: [ExprStmt] ...; +# 19| 0: [MethodCall] call to method WriteLine +# 19| -1: [TypeAccess] access to type Console +# 19| 0: [StringLiteral] "Base.F" +# 22| 9: [Class] C +# 26| 2: [Class] Derived +#-----| 3: (Base types) +# 26| 0: [Class] Base +# 29| 5: [Class] Nested +# 32| 5: [Method] G +# 33| 4: [BlockStmt] {...} +# 34| 0: [LocalVariableDeclStmt] ... ...; +# 34| 0: [LocalVariableDeclAndInitExpr] Derived d = ... +# 34| 0: [ObjectCreation] object creation of type Derived +# 34| 1: [LocalVariableAccess] access to local variable d +# 35| 1: [ExprStmt] ...; +# 35| 0: [MethodCall] call to method F +# 35| -1: [LocalVariableAccess] access to local variable d +# 42| 3: [Class] Test +# 45| 5: [Method] Main +# 46| 4: [BlockStmt] {...} +# 47| 0: [LocalVariableDeclStmt] ... ...; +# 47| 0: [LocalVariableDeclAndInitExpr] Nested n = ... +# 47| 0: [ObjectCreation] object creation of type Nested +# 47| 1: [LocalVariableAccess] access to local variable n +# 48| 1: [ExprStmt] ...; +# 48| 0: [MethodCall] call to method G +# 48| -1: [LocalVariableAccess] access to local variable n +# 53| 4: [Class] Outer<> +#-----| 1: (Type parameters) +# 53| 0: [TypeParameter] T +# 56| 5: [Class] Inner<> +#-----| 1: (Type parameters) +# 56| 0: [TypeParameter] U +# 59| 5: [Method] F +#-----| 2: (Parameters) +# 59| 0: [Parameter] t +# 59| 1: [Parameter] u +# 59| 4: [BlockStmt] {...} +# 63| 7: [Method] F +#-----| 2: (Parameters) +# 63| 0: [Parameter] t +# 64| 4: [BlockStmt] {...} +# 65| 0: [ExprStmt] ...; +# 65| 0: [MethodCall] call to method F +# 65| -1: [TypeAccess] access to type Inner +# 65| -1: [TypeAccess] access to type Outer<> +# 65| 0: [ParameterAccess] access to parameter t +# 65| 1: [StringLiteral] "abc" +# 68| 1: [ExprStmt] ...; +# 68| 0: [MethodCall] call to method F +# 68| -1: [TypeAccess] access to type Inner +# 68| -1: [TypeAccess] access to type Outer +# 68| 0: [IntLiteral] 3 +# 68| 1: [StringLiteral] "abc" +# 69| 2: [LocalVariableDeclStmt] ... ...; +# 69| 0: [LocalVariableDeclAndInitExpr] Type type = ... +# 69| 0: [TypeofExpr] typeof(...) +# 69| 0: [TypeAccess] access to type Inner<> +# 69| 1: [LocalVariableAccess] access to local variable type +# 74| 5: [Class] Outer2<> +#-----| 1: (Type parameters) +# 74| 0: [TypeParameter] T +# 77| 5: [Class] Inner2<> +#-----| 1: (Type parameters) +# 77| 0: [TypeParameter] T +# 80| 5: [Field] t diff --git a/csharp/ql/test/library-tests/nestedtypes/PrintAst.qlref b/csharp/ql/test/library-tests/nestedtypes/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/nestedtypes/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/operators/PrintAst.expected b/csharp/ql/test/library-tests/operators/PrintAst.expected new file mode 100644 index 00000000000..2aa62e022ca --- /dev/null +++ b/csharp/ql/test/library-tests/operators/PrintAst.expected @@ -0,0 +1,129 @@ +operators.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 7| 1: [Class] IntVector +# 10| 4: [InstanceConstructor] IntVector +#-----| 2: (Parameters) +# 10| 0: [Parameter] length +# 10| 4: [BlockStmt] {...} +# 12| 5: [Property] Length +# 12| 3: [Getter] get_Length +# 12| 4: [BlockStmt] {...} +# 12| 0: [ReturnStmt] return ...; +# 12| 0: [IntLiteral] 4 +# 14| 6: [Indexer] Item +#-----| 1: (Parameters) +# 14| 0: [Parameter] index +# 14| 3: [Getter] get_Item +#-----| 2: (Parameters) +# 14| 0: [Parameter] index +# 14| 4: [BlockStmt] {...} +# 14| 0: [ReturnStmt] return ...; +# 14| 0: [IntLiteral] 0 +# 14| 4: [Setter] set_Item +#-----| 2: (Parameters) +# 14| 0: [Parameter] index +# 14| 1: [Parameter] value +# 14| 4: [BlockStmt] {...} +# 16| 7: [IncrementOperator] ++ +#-----| 2: (Parameters) +# 16| 0: [Parameter] iv +# 17| 4: [BlockStmt] {...} +# 18| 0: [LocalVariableDeclStmt] ... ...; +# 18| 0: [LocalVariableDeclAndInitExpr] IntVector temp = ... +# 18| 0: [ObjectCreation] object creation of type IntVector +# 18| 0: [PropertyCall] access to property Length +# 18| -1: [ParameterAccess] access to parameter iv +# 18| 1: [LocalVariableAccess] access to local variable temp +# 19| 1: [ForStmt] for (...;...;...) ... +# 19| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 19| 0: [IntLiteral] 0 +# 19| 1: [LocalVariableAccess] access to local variable i +# 19| 0: [LTExpr] ... < ... +# 19| 0: [LocalVariableAccess] access to local variable i +# 19| 1: [PropertyCall] access to property Length +# 19| -1: [ParameterAccess] access to parameter iv +# 19| 1: [PostIncrExpr] ...++ +# 19| 0: [LocalVariableAccess] access to local variable i +# 20| 2: [ExprStmt] ...; +# 20| 0: [AssignExpr] ... = ... +# 20| 0: [AddExpr] ... + ... +# 20| 0: [IndexerCall] access to indexer +# 20| -1: [ParameterAccess] access to parameter iv +# 20| 0: [LocalVariableAccess] access to local variable i +# 20| 1: [IntLiteral] 1 +# 20| 1: [IndexerCall] access to indexer +# 20| -1: [LocalVariableAccess] access to local variable temp +# 20| 0: [LocalVariableAccess] access to local variable i +# 21| 2: [ReturnStmt] return ...; +# 21| 0: [LocalVariableAccess] access to local variable temp +# 26| 2: [Class] TestUnaryOperator +# 29| 5: [Method] Main +# 30| 4: [BlockStmt] {...} +# 31| 0: [LocalVariableDeclStmt] ... ...; +# 31| 0: [LocalVariableDeclAndInitExpr] IntVector iv1 = ... +# 31| 0: [ObjectCreation] object creation of type IntVector +# 31| 0: [IntLiteral] 4 +# 31| 1: [LocalVariableAccess] access to local variable iv1 +# 32| 1: [LocalVariableDeclStmt] ... ...; +# 32| 0: [LocalVariableDeclExpr] IntVector iv2 +# 33| 2: [ExprStmt] ...; +# 33| 0: [AssignExpr] ... = ... +# 33| 0: [OperatorCall] call to operator ++ +# 33| 0: [LocalVariableAccess] access to local variable iv1 +# 33| 1: [LocalVariableAccess] access to local variable iv2 +# 34| 3: [ExprStmt] ...; +# 34| 0: [AssignExpr] ... = ... +# 34| 0: [OperatorCall] call to operator ++ +# 34| 0: [LocalVariableAccess] access to local variable iv1 +# 34| 1: [LocalVariableAccess] access to local variable iv2 +# 39| 3: [Struct] Digit +# 42| 5: [Field] value +# 44| 6: [InstanceConstructor] Digit +#-----| 2: (Parameters) +# 44| 0: [Parameter] value +# 45| 4: [BlockStmt] {...} +# 46| 0: [IfStmt] if (...) ... +# 46| 0: [LogicalOrExpr] ... || ... +# 46| 0: [LTExpr] ... < ... +# 46| 0: [CastExpr] (...) ... +# 46| 0: [ParameterAccess] access to parameter value +# 46| 1: [IntLiteral] 0 +# 46| 1: [GTExpr] ... > ... +# 46| 0: [CastExpr] (...) ... +# 46| 0: [ParameterAccess] access to parameter value +# 46| 1: [IntLiteral] 9 +# 47| 1: [ThrowStmt] throw ...; +# 47| 0: [ObjectCreation] object creation of type ArgumentException +# 48| 1: [ExprStmt] ...; +# 48| 0: [AssignExpr] ... = ... +# 48| 0: [ParameterAccess] access to parameter value +# 48| 1: [FieldAccess] access to field value +# 48| -1: [ThisAccess] this access +# 51| 7: [ImplicitConversionOperator] implicit conversion +#-----| 2: (Parameters) +# 51| 0: [Parameter] d +# 52| 4: [BlockStmt] {...} +# 53| 0: [ReturnStmt] return ...; +# 53| 0: [FieldAccess] access to field value +# 53| -1: [ParameterAccess] access to parameter d +# 56| 8: [ExplicitConversionOperator] explicit conversion +#-----| 2: (Parameters) +# 56| 0: [Parameter] b +# 57| 4: [BlockStmt] {...} +# 58| 0: [ReturnStmt] return ...; +# 58| 0: [ObjectCreation] object creation of type Digit +# 58| 0: [ParameterAccess] access to parameter b +# 63| 4: [Class] TestConversionOperator +# 66| 5: [Method] Main +# 67| 4: [BlockStmt] {...} +# 68| 0: [LocalVariableDeclStmt] ... ...; +# 68| 0: [LocalVariableDeclAndInitExpr] Digit d = ... +# 68| 0: [OperatorCall] call to operator explicit conversion +# 68| 0: [CastExpr] (...) ... +# 68| 0: [IntLiteral] 8 +# 68| 1: [LocalVariableAccess] access to local variable d +# 69| 1: [LocalVariableDeclStmt] ... ...; +# 69| 0: [LocalVariableDeclAndInitExpr] Byte b = ... +# 69| 0: [OperatorCall] call to operator implicit conversion +# 69| 0: [LocalVariableAccess] access to local variable d +# 69| 1: [LocalVariableAccess] access to local variable b diff --git a/csharp/ql/test/library-tests/operators/PrintAst.qlref b/csharp/ql/test/library-tests/operators/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/operators/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/partial/MethodIsPartial.expected b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected new file mode 100644 index 00000000000..8ee8f25b0c8 --- /dev/null +++ b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected @@ -0,0 +1,7 @@ +| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | true | +| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | true | +| Partial.cs:5:17:5:23 | Method2 | false | +| Partial.cs:11:17:11:23 | Method3 | false | +| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | true | +| Partial.cs:17:17:17:23 | Method4 | false | +| Partial.cs:22:17:22:23 | Method5 | false | diff --git a/csharp/ql/test/library-tests/partial/MethodIsPartial.ql b/csharp/ql/test/library-tests/partial/MethodIsPartial.ql new file mode 100644 index 00000000000..b7e50bd5a44 --- /dev/null +++ b/csharp/ql/test/library-tests/partial/MethodIsPartial.ql @@ -0,0 +1,7 @@ +import csharp + +private boolean isPartial(Method m) { if m.isPartial() then result = true else result = false } + +from Method m +where m.fromSource() +select m, isPartial(m) diff --git a/csharp/ql/test/library-tests/partial/Partial.cs b/csharp/ql/test/library-tests/partial/Partial.cs index e8efae8c52f..1d54614fc86 100644 --- a/csharp/ql/test/library-tests/partial/Partial.cs +++ b/csharp/ql/test/library-tests/partial/Partial.cs @@ -1,11 +1,23 @@ -partial class A +partial class TwoPartClass { - partial void M(); - public void M2() { } + partial void PartialMethodWithBody1(); + partial void PartialMethodWithoutBody1(); + public void Method2() { } } -partial class A +partial class TwoPartClass { - partial void M() { } - public void M3() { } + partial void PartialMethodWithBody1() { } + public void Method3() { } } + +partial class OnePartPartialClass +{ + partial void PartialMethodWithoutBody2(); + public void Method4() { } +} + +class NonPartialClass +{ + public void Method5() { } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/partial/Partial1.expected b/csharp/ql/test/library-tests/partial/Partial1.expected index 3cc137e832f..722482cac4f 100644 --- a/csharp/ql/test/library-tests/partial/Partial1.expected +++ b/csharp/ql/test/library-tests/partial/Partial1.expected @@ -1,3 +1,6 @@ -| Partial.cs:1:15:1:15 | A | -| Partial.cs:3:18:3:18 | M | -| Partial.cs:7:15:7:15 | A | +| Partial.cs:1:15:1:26 | TwoPartClass | +| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | +| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | +| Partial.cs:8:15:8:26 | TwoPartClass | +| Partial.cs:14:15:14:33 | OnePartPartialClass | +| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | diff --git a/csharp/ql/test/library-tests/partial/Partial2.expected b/csharp/ql/test/library-tests/partial/Partial2.expected index 079601bb497..6723b575fc7 100644 --- a/csharp/ql/test/library-tests/partial/Partial2.expected +++ b/csharp/ql/test/library-tests/partial/Partial2.expected @@ -1,6 +1,10 @@ -| Partial.cs:1:15:1:15 | A | Partial.cs:3:18:3:18 | M | -| Partial.cs:1:15:1:15 | A | Partial.cs:4:17:4:18 | M2 | -| Partial.cs:1:15:1:15 | A | Partial.cs:10:17:10:18 | M3 | -| Partial.cs:7:15:7:15 | A | Partial.cs:3:18:3:18 | M | -| Partial.cs:7:15:7:15 | A | Partial.cs:4:17:4:18 | M2 | -| Partial.cs:7:15:7:15 | A | Partial.cs:10:17:10:18 | M3 | +| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:3:18:3:39 | PartialMethodWithBody1 | +| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | +| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 | +| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 | +| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:3:18:3:39 | PartialMethodWithBody1 | +| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | +| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 | +| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 | +| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | +| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:17:17:17:23 | Method4 | diff --git a/csharp/ql/test/library-tests/partial/PartialMethodBody.expected b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected new file mode 100644 index 00000000000..e6592704f1a --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected @@ -0,0 +1,3 @@ +| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | true | +| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | false | +| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | false | diff --git a/csharp/ql/test/library-tests/partial/PartialMethodBody.ql b/csharp/ql/test/library-tests/partial/PartialMethodBody.ql new file mode 100644 index 00000000000..53cb9be250a --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PartialMethodBody.ql @@ -0,0 +1,7 @@ +import csharp + +private boolean hasBody(Method m) { if m.hasBody() then result = true else result = false } + +from Method m +where m.fromSource() and m.isPartial() +select m, hasBody(m) diff --git a/csharp/ql/test/library-tests/partial/PrintAst.expected b/csharp/ql/test/library-tests/partial/PrintAst.expected new file mode 100644 index 00000000000..c250c86c66d --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PrintAst.expected @@ -0,0 +1,16 @@ +Partial.cs: +# 1| [Class] TwoPartClass +# 3| 5: [Method] PartialMethodWithBody1 +# 10| 4: [BlockStmt] {...} +# 4| 6: [Method] PartialMethodWithoutBody1 +# 5| 7: [Method] Method2 +# 5| 4: [BlockStmt] {...} +# 11| 8: [Method] Method3 +# 11| 4: [BlockStmt] {...} +# 14| [Class] OnePartPartialClass +# 16| 5: [Method] PartialMethodWithoutBody2 +# 17| 6: [Method] Method4 +# 17| 4: [BlockStmt] {...} +# 20| [Class] NonPartialClass +# 22| 5: [Method] Method5 +# 22| 4: [BlockStmt] {...} diff --git a/csharp/ql/test/library-tests/partial/PrintAst.qlref b/csharp/ql/test/library-tests/partial/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/partial/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/properties/PrintAst.expected b/csharp/ql/test/library-tests/properties/PrintAst.expected new file mode 100644 index 00000000000..8d3daf118f5 --- /dev/null +++ b/csharp/ql/test/library-tests/properties/PrintAst.expected @@ -0,0 +1,194 @@ +properties.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 7| 1: [Class] Button +# 10| 5: [Field] caption +# 12| 6: [IndexerProperty] Caption +# 15| 3: [Getter] get_Caption +# 15| 4: [BlockStmt] {...} +# 15| 0: [ReturnStmt] return ...; +# 15| 0: [FieldAccess] access to field caption +# 17| 4: [Setter] set_Caption +#-----| 2: (Parameters) +# 17| 0: [Parameter] value +# 18| 4: [BlockStmt] {...} +# 19| 0: [IfStmt] if (...) ... +# 19| 0: [NEExpr] ... != ... +# 19| 0: [FieldAccess] access to field caption +# 19| 1: [ParameterAccess] access to parameter value +# 20| 1: [BlockStmt] {...} +# 21| 0: [ExprStmt] ...; +# 21| 0: [AssignExpr] ... = ... +# 21| 0: [ParameterAccess] access to parameter value +# 21| 1: [FieldAccess] access to field caption +# 26| 7: [Method] Paint +# 27| 4: [BlockStmt] {...} +# 28| 0: [LocalVariableDeclStmt] ... ...; +# 28| 0: [LocalVariableDeclAndInitExpr] Button okButton = ... +# 28| 0: [ObjectCreation] object creation of type Button +# 28| 1: [LocalVariableAccess] access to local variable okButton +# 29| 1: [ExprStmt] ...; +# 29| 0: [AssignExpr] ... = ... +# 29| 0: [StringLiteral] "OK" +# 29| 1: [PropertyCall] access to property Caption +# 29| -1: [LocalVariableAccess] access to local variable okButton +# 30| 2: [LocalVariableDeclStmt] ... ...; +# 30| 0: [LocalVariableDeclAndInitExpr] String s = ... +# 30| 0: [PropertyCall] access to property Caption +# 30| -1: [LocalVariableAccess] access to local variable okButton +# 30| 1: [LocalVariableAccess] access to local variable s +# 34| 2: [Class] Counter +# 37| 5: [Field] next +# 39| 6: [Property] Next +# 41| 3: [Getter] get_Next +# 41| 4: [BlockStmt] {...} +# 41| 0: [ReturnStmt] return ...; +# 41| 0: [PostIncrExpr] ...++ +# 41| 0: [FieldAccess] access to field next +# 46| 3: [Class] Point +# 49| 5: [Property] X +# 49| 3: [Getter] get_X +# 49| 4: [Setter] set_X +#-----| 2: (Parameters) +# 49| 0: [Parameter] value +# 50| 6: [Property] Y +# 50| 3: [Getter] get_Y +# 50| 4: [Setter] set_Y +#-----| 2: (Parameters) +# 50| 0: [Parameter] value +# 54| 4: [Class] ReadOnlyPoint +# 57| 4: [Property] X +# 57| 3: [Getter] get_X +# 57| 4: [Setter] set_X +#-----| 2: (Parameters) +# 57| 0: [Parameter] value +# 58| 5: [Property] Y +# 58| 3: [Getter] get_Y +# 58| 4: [Setter] set_Y +#-----| 2: (Parameters) +# 58| 0: [Parameter] value +# 59| 6: [InstanceConstructor] ReadOnlyPoint +#-----| 2: (Parameters) +# 59| 0: [Parameter] x +# 59| 1: [Parameter] y +# 60| 4: [BlockStmt] {...} +# 61| 0: [ExprStmt] ...; +# 61| 0: [AssignExpr] ... = ... +# 61| 0: [ParameterAccess] access to parameter x +# 61| 1: [PropertyCall] access to property X +# 62| 1: [ExprStmt] ...; +# 62| 0: [AssignExpr] ... = ... +# 62| 0: [ParameterAccess] access to parameter y +# 62| 1: [PropertyCall] access to property Y +# 67| 5: [Class] A +# 69| 5: [Field] y +# 70| 6: [Property] X +# 70| 3: [Getter] get_X +# 70| 4: [BlockStmt] {...} +# 70| 0: [ReturnStmt] return ...; +# 70| 0: [IntLiteral] 0 +# 71| 7: [Property] Y +# 73| 3: [Getter] get_Y +# 73| 4: [BlockStmt] {...} +# 73| 0: [ReturnStmt] return ...; +# 73| 0: [FieldAccess] access to field y +# 74| 4: [Setter] set_Y +#-----| 2: (Parameters) +# 74| 0: [Parameter] value +# 74| 4: [BlockStmt] {...} +# 74| 0: [ExprStmt] ...; +# 74| 0: [AssignExpr] ... = ... +# 74| 0: [ParameterAccess] access to parameter value +# 74| 1: [FieldAccess] access to field y +# 76| 8: [Property] Z +# 76| 3: [Getter] get_Z +# 76| 4: [Setter] set_Z +#-----| 2: (Parameters) +# 76| 0: [Parameter] value +# 79| 6: [Class] B +#-----| 3: (Base types) +# 79| 0: [Class] A +# 81| 5: [Field] z +# 82| 6: [Property] X +# 82| 3: [Getter] get_X +# 82| 4: [BlockStmt] {...} +# 82| 0: [ReturnStmt] return ...; +# 82| 0: [AddExpr] ... + ... +# 82| 0: [PropertyCall] access to property X +# 82| -1: [BaseAccess] base access +# 82| 1: [IntLiteral] 1 +# 83| 7: [Property] Y +# 83| 3: [Setter] set_Y +#-----| 2: (Parameters) +# 83| 0: [Parameter] value +# 83| 4: [BlockStmt] {...} +# 83| 0: [ExprStmt] ...; +# 83| 0: [AssignExpr] ... = ... +# 83| 0: [ConditionalExpr] ... ? ... : ... +# 83| 0: [LTExpr] ... < ... +# 83| 0: [ParameterAccess] access to parameter value +# 83| 1: [IntLiteral] 0 +# 83| 1: [IntLiteral] 0 +# 83| 2: [ParameterAccess] access to parameter value +# 83| 1: [PropertyCall] access to property Y +# 83| -1: [BaseAccess] base access +# 84| 8: [Property] Z +# 86| 3: [Getter] get_Z +# 86| 4: [BlockStmt] {...} +# 86| 0: [ReturnStmt] return ...; +# 86| 0: [FieldAccess] access to field z +# 87| 4: [Setter] set_Z +#-----| 2: (Parameters) +# 87| 0: [Parameter] value +# 87| 4: [BlockStmt] {...} +# 87| 0: [ExprStmt] ...; +# 87| 0: [AssignExpr] ... = ... +# 87| 0: [ParameterAccess] access to parameter value +# 87| 1: [FieldAccess] access to field z +# 91| 7: [Class] Test +# 93| 5: [Property] Init +# 93| 3: [Setter] set_Init +#-----| 2: (Parameters) +# 93| 0: [Parameter] value +# 93| 4: [BlockStmt] {...} +# 94| 6: [Method] Main +# 95| 4: [BlockStmt] {...} +# 96| 0: [LocalVariableDeclStmt] ... ...; +# 96| 0: [LocalVariableDeclAndInitExpr] List ds = ... +# 96| 0: [ObjectCreation] object creation of type List +# 96| 1: [LocalVariableAccess] access to local variable ds +# 97| 1: [LocalVariableDeclStmt] ... ...; +# 97| 0: [LocalVariableDeclAndInitExpr] List os = ... +# 97| 0: [ObjectCreation] object creation of type List +# 97| 1: [LocalVariableAccess] access to local variable os +# 98| 2: [IfStmt] if (...) ... +# 98| 0: [EQExpr] ... == ... +# 98| 0: [PropertyCall] access to property Count +# 98| -1: [LocalVariableAccess] access to local variable ds +# 98| 1: [PropertyCall] access to property Count +# 98| -1: [LocalVariableAccess] access to local variable os +# 99| 1: [BlockStmt] {...} +# 104| 8: [Interface] InterfaceWithProperties +# 106| 4: [Property] Prop1 +# 106| 3: [Getter] get_Prop1 +# 107| 5: [Property] Prop2 +# 107| 3: [Setter] set_Prop2 +#-----| 2: (Parameters) +# 107| 0: [Parameter] value +# 110| 9: [Class] ImplementsProperties +#-----| 3: (Base types) +# 110| 1: [Interface] InterfaceWithProperties +# 112| 5: [Property] Prop1 +# 114| 3: [Getter] get_Prop1 +# 114| 4: [BlockStmt] {...} +# 114| 0: [ReturnStmt] return ...; +# 114| 0: [IntLiteral] 0 +# 117| 6: [Property] Prop2 +# 119| 3: [Setter] set_Prop2 +#-----| 2: (Parameters) +# 119| 0: [Parameter] value +# 119| 4: [BlockStmt] {...} +# 122| 7: [Property] Prop2 +# 124| 3: [Setter] set_Prop2 +#-----| 2: (Parameters) +# 124| 0: [Parameter] value +# 124| 4: [BlockStmt] {...} diff --git a/csharp/ql/test/library-tests/properties/PrintAst.qlref b/csharp/ql/test/library-tests/properties/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/properties/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/statements/PrintAst.expected b/csharp/ql/test/library-tests/statements/PrintAst.expected new file mode 100644 index 00000000000..11eac4e2c28 --- /dev/null +++ b/csharp/ql/test/library-tests/statements/PrintAst.expected @@ -0,0 +1,579 @@ +fixed.cs: +# 3| [Class] Fixed +# 5| 5: [Method] fixed1 +# 6| 4: [BlockStmt] {...} +# 7| 0: [LocalVariableDeclStmt] ... ...; +# 7| 0: [LocalVariableDeclAndInitExpr] Byte[] buffer = ... +# 7| 0: [ArrayCreation] array creation of type Byte[] +# 7| 0: [IntLiteral] 10 +# 7| 1: [LocalVariableAccess] access to local variable buffer +# 9| 1: [FixedStmt] fixed(...) { ... } +# 9| -1: [LocalVariableDeclAndInitExpr] Byte* pinned_buffer = ... +# 9| 0: [AddressOfExpr] &... +# 9| 0: [ArrayAccess] access to array element +# 9| -1: [LocalVariableAccess] access to local variable buffer +# 9| 0: [IntLiteral] 0 +# 9| 1: [LocalVariableAccess] access to local variable pinned_buffer +# 10| 0: [BlockStmt] {...} +# 11| 0: [LocalVariableDeclStmt] ... ...; +# 11| 0: [LocalVariableDeclAndInitExpr] Byte* t = ... +# 11| 0: [LocalVariableAccess] access to local variable pinned_buffer +# 11| 1: [LocalVariableAccess] access to local variable t +# 12| 1: [ExprStmt] ...; +# 12| 0: [MethodCall] call to method fixed1 +# 15| 2: [FixedStmt] fixed(...) { ... } +# 15| -1: [LocalVariableDeclAndInitExpr] Byte* pinned_buffer = ... +# 15| 0: [AddressOfExpr] &... +# 15| 0: [ArrayAccess] access to array element +# 15| -1: [LocalVariableAccess] access to local variable buffer +# 15| 0: [IntLiteral] 0 +# 15| 1: [LocalVariableAccess] access to local variable pinned_buffer +# 16| 0: [BlockStmt] {...} +# 19| 3: [FixedStmt] fixed(...) { ... } +# 19| -1: [LocalVariableDeclAndInitExpr] Byte* pinned_buffer = ... +# 19| 0: [AddressOfExpr] &... +# 19| 0: [ArrayAccess] access to array element +# 19| -1: [LocalVariableAccess] access to local variable buffer +# 19| 0: [IntLiteral] 0 +# 19| 1: [LocalVariableAccess] access to local variable pinned_buffer +# 19| 0: [EmptyStmt] ; +statements.cs: +# 5| [NamespaceDeclaration] namespace ... { ... } +# 7| 1: [Class] Class +# 10| 5: [Method] Main +# 11| 4: [BlockStmt] {...} +# 12| 0: [LabelStmt] block: +# 13| 1: [BlockStmt] {...} +# 14| 0: [BlockStmt] {...} +# 16| 1: [BlockStmt] {...} +# 17| 0: [BlockStmt] {...} +# 23| 6: [Method] MainEmpty +# 24| 4: [BlockStmt] {...} +# 25| 0: [LocalVariableDeclStmt] ... ...; +# 25| 0: [LocalVariableDeclAndInitExpr] Class c = ... +# 25| 0: [ObjectCreation] object creation of type Class +# 25| 1: [LocalVariableAccess] access to local variable c +# 26| 1: [EmptyStmt] ; +# 26| 2: [EmptyStmt] ; +# 26| 3: [EmptyStmt] ; +# 27| 4: [IfStmt] if (...) ... +# 27| 0: [BoolLiteral] true +# 27| 1: [EmptyStmt] ; +# 30| 7: [Method] MainLocalVarDecl +# 31| 4: [BlockStmt] {...} +# 32| 0: [LocalVariableDeclStmt] ... ...; +# 32| 0: [LocalVariableDeclExpr] Int32 a +# 33| 1: [LocalVariableDeclStmt] ... ...; +# 33| 0: [LocalVariableDeclAndInitExpr] Int32 b = ... +# 33| 0: [IntLiteral] 2 +# 33| 1: [LocalVariableAccess] access to local variable b +# 33| 1: [LocalVariableDeclAndInitExpr] Int32 c = ... +# 33| 0: [IntLiteral] 3 +# 33| 1: [LocalVariableAccess] access to local variable c +# 34| 2: [ExprStmt] ...; +# 34| 0: [AssignExpr] ... = ... +# 34| 0: [IntLiteral] 1 +# 34| 1: [LocalVariableAccess] access to local variable a +# 35| 3: [ExprStmt] ...; +# 35| 0: [MethodCall] call to method WriteLine +# 35| -1: [TypeAccess] access to type Console +# 35| 0: [AddExpr] ... + ... +# 35| 0: [AddExpr] ... + ... +# 35| 0: [LocalVariableAccess] access to local variable a +# 35| 1: [LocalVariableAccess] access to local variable b +# 35| 1: [LocalVariableAccess] access to local variable c +# 36| 4: [LocalVariableDeclStmt] ... ...; +# 36| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 36| 0: [IntLiteral] 45 +# 36| 1: [LocalVariableAccess] access to local variable x +# 37| 5: [LocalVariableDeclStmt] ... ...; +# 37| 0: [LocalVariableDeclAndInitExpr] String y = ... +# 37| 0: [StringLiteral] "test" +# 37| 1: [LocalVariableAccess] access to local variable y +# 40| 8: [Method] MainLocalConstDecl +# 41| 4: [BlockStmt] {...} +# 42| 0: [LocalConstantDeclStmt] const ... ...; +# 42| 0: [LocalVariableDeclAndInitExpr] Single pi = ... +# 42| 0: [FloatLiteral] 3.1415927 +# 42| 1: [LocalVariableAccess] access to local variable pi +# 43| 1: [LocalConstantDeclStmt] const ... ...; +# 43| 0: [LocalVariableDeclAndInitExpr] Int32 r = ... +# 43| 0: [AddExpr] ... + ... +# 43| 0: [IntLiteral] 5 +# 43| 1: [IntLiteral] 20 +# 43| 1: [LocalVariableAccess] access to local variable r +# 44| 2: [ExprStmt] ...; +# 44| 0: [MethodCall] call to method WriteLine +# 44| -1: [TypeAccess] access to type Console +# 44| 0: [MulExpr] ... * ... +# 44| 0: [MulExpr] ... * ... +# 44| 0: [LocalVariableAccess] access to local variable pi +# 44| 1: [CastExpr] (...) ... +# 44| 0: [LocalVariableAccess] access to local variable r +# 44| 1: [CastExpr] (...) ... +# 44| 0: [LocalVariableAccess] access to local variable r +# 47| 9: [Method] MainExpr +# 48| 4: [BlockStmt] {...} +# 49| 0: [LocalVariableDeclStmt] ... ...; +# 49| 0: [LocalVariableDeclExpr] Int32 i +# 50| 1: [ExprStmt] ...; +# 50| 0: [AssignExpr] ... = ... +# 50| 0: [IntLiteral] 123 +# 50| 1: [LocalVariableAccess] access to local variable i +# 51| 2: [ExprStmt] ...; +# 51| 0: [MethodCall] call to method WriteLine +# 51| -1: [TypeAccess] access to type Console +# 51| 0: [LocalVariableAccess] access to local variable i +# 52| 3: [ExprStmt] ...; +# 52| 0: [PostIncrExpr] ...++ +# 52| 0: [LocalVariableAccess] access to local variable i +# 53| 4: [ExprStmt] ...; +# 53| 0: [MethodCall] call to method WriteLine +# 53| -1: [TypeAccess] access to type Console +# 53| 0: [LocalVariableAccess] access to local variable i +# 56| 10: [Method] MainIf +#-----| 2: (Parameters) +# 56| 0: [Parameter] args +# 57| 4: [BlockStmt] {...} +# 58| 0: [IfStmt] if (...) ... +# 58| 0: [EQExpr] ... == ... +# 58| 0: [PropertyCall] access to property Length +# 58| -1: [ParameterAccess] access to parameter args +# 58| 1: [IntLiteral] 0 +# 59| 1: [BlockStmt] {...} +# 60| 0: [ExprStmt] ...; +# 60| 0: [MethodCall] call to method WriteLine +# 60| -1: [TypeAccess] access to type Console +# 60| 0: [StringLiteral] "No arguments" +# 63| 2: [BlockStmt] {...} +# 64| 0: [ExprStmt] ...; +# 64| 0: [MethodCall] call to method WriteLine +# 64| -1: [TypeAccess] access to type Console +# 64| 0: [StringLiteral] "One or more arguments" +# 69| 11: [Method] MainSwitch +#-----| 2: (Parameters) +# 69| 0: [Parameter] args +# 70| 4: [BlockStmt] {...} +# 71| 0: [LocalVariableDeclStmt] ... ...; +# 71| 0: [LocalVariableDeclAndInitExpr] Int32 n = ... +# 71| 0: [PropertyCall] access to property Length +# 71| -1: [ParameterAccess] access to parameter args +# 71| 1: [LocalVariableAccess] access to local variable n +# 72| 1: [SwitchStmt] switch (...) {...} +# 72| 0: [LocalVariableAccess] access to local variable n +# 74| 0: [ConstCase] case ...: +# 74| 0: [ConstantPatternExpr,IntLiteral] 0 +# 75| 1: [ExprStmt] ...; +# 75| 0: [MethodCall] call to method WriteLine +# 75| -1: [TypeAccess] access to type Console +# 75| 0: [StringLiteral] "No arguments" +# 76| 2: [BreakStmt] break; +# 77| 3: [ConstCase] case ...: +# 77| 0: [ConstantPatternExpr,IntLiteral] 1 +# 78| 4: [ExprStmt] ...; +# 78| 0: [MethodCall] call to method WriteLine +# 78| -1: [TypeAccess] access to type Console +# 78| 0: [StringLiteral] "One argument" +# 79| 5: [BreakStmt] break; +# 80| 6: [DefaultCase] default: +# 81| 7: [ExprStmt] ...; +# 81| 0: [MethodCall] call to method WriteLine +# 81| -1: [TypeAccess] access to type Console +# 81| 0: [StringLiteral] "{0} arguments" +# 81| 1: [CastExpr] (...) ... +# 81| 0: [LocalVariableAccess] access to local variable n +# 82| 8: [BreakStmt] break; +# 86| 12: [Method] StringSwitch +#-----| 2: (Parameters) +# 86| 0: [Parameter] foo +# 87| 4: [BlockStmt] {...} +# 88| 0: [SwitchStmt] switch (...) {...} +# 88| 0: [ParameterAccess] access to parameter foo +# 90| 0: [ConstCase] case ...: +# 90| 0: [ConstantPatternExpr,StringLiteral] "black" +# 91| 1: [ReturnStmt] return ...; +# 91| 0: [IntLiteral] 0 +# 92| 2: [ConstCase] case ...: +# 92| 0: [ConstantPatternExpr,StringLiteral] "red" +# 93| 3: [ReturnStmt] return ...; +# 93| 0: [IntLiteral] 1 +# 94| 4: [ConstCase] case ...: +# 94| 0: [ConstantPatternExpr,StringLiteral] "green" +# 95| 5: [ReturnStmt] return ...; +# 95| 0: [IntLiteral] 2 +# 96| 6: [ConstCase] case ...: +# 96| 0: [ConstantPatternExpr,StringLiteral] "yellow" +# 97| 7: [ReturnStmt] return ...; +# 97| 0: [IntLiteral] 3 +# 98| 8: [ConstCase] case ...: +# 98| 0: [ConstantPatternExpr,StringLiteral] "blue" +# 99| 9: [ReturnStmt] return ...; +# 99| 0: [IntLiteral] 4 +# 100| 10: [ConstCase] case ...: +# 100| 0: [ConstantPatternExpr,StringLiteral] "magenta" +# 101| 11: [ReturnStmt] return ...; +# 101| 0: [IntLiteral] 5 +# 102| 12: [ConstCase] case ...: +# 102| 0: [ConstantPatternExpr,StringLiteral] "cyan" +# 103| 13: [ReturnStmt] return ...; +# 103| 0: [IntLiteral] 6 +# 104| 14: [ConstCase] case ...: +# 104| 0: [ConstantPatternExpr,StringLiteral] "grey" +# 105| 15: [ConstCase] case ...: +# 105| 0: [ConstantPatternExpr,StringLiteral] "white" +# 106| 16: [ReturnStmt] return ...; +# 106| 0: [IntLiteral] 7 +# 108| 1: [ReturnStmt] return ...; +# 108| 0: [IntLiteral] 7 +# 111| 13: [Method] MainWhile +#-----| 2: (Parameters) +# 111| 0: [Parameter] args +# 112| 4: [BlockStmt] {...} +# 113| 0: [LocalVariableDeclStmt] ... ...; +# 113| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 113| 0: [IntLiteral] 0 +# 113| 1: [LocalVariableAccess] access to local variable i +# 114| 1: [WhileStmt] while (...) ... +# 114| 0: [LTExpr] ... < ... +# 114| 0: [LocalVariableAccess] access to local variable i +# 114| 1: [PropertyCall] access to property Length +# 114| -1: [ParameterAccess] access to parameter args +# 115| 1: [BlockStmt] {...} +# 116| 0: [ExprStmt] ...; +# 116| 0: [MethodCall] call to method WriteLine +# 116| -1: [TypeAccess] access to type Console +# 116| 0: [ArrayAccess] access to array element +# 116| -1: [ParameterAccess] access to parameter args +# 116| 0: [LocalVariableAccess] access to local variable i +# 117| 1: [ExprStmt] ...; +# 117| 0: [PostIncrExpr] ...++ +# 117| 0: [LocalVariableAccess] access to local variable i +# 121| 14: [Method] MainDo +# 122| 4: [BlockStmt] {...} +# 123| 0: [LocalVariableDeclStmt] ... ...; +# 123| 0: [LocalVariableDeclExpr] String s +# 124| 1: [DoStmt] do ... while (...); +# 128| 0: [NEExpr] ... != ... +# 128| 0: [LocalVariableAccess] access to local variable s +# 128| 1: [NullLiteral] null +# 125| 1: [BlockStmt] {...} +# 126| 0: [ExprStmt] ...; +# 126| 0: [AssignExpr] ... = ... +# 126| 0: [MethodCall] call to method ReadLine +# 126| -1: [TypeAccess] access to type Console +# 126| 1: [LocalVariableAccess] access to local variable s +# 127| 1: [IfStmt] if (...) ... +# 127| 0: [NEExpr] ... != ... +# 127| 0: [LocalVariableAccess] access to local variable s +# 127| 1: [NullLiteral] null +# 127| 1: [ExprStmt] ...; +# 127| 0: [MethodCall] call to method WriteLine +# 127| -1: [TypeAccess] access to type Console +# 127| 0: [LocalVariableAccess] access to local variable s +# 131| 15: [Method] MainFor +#-----| 2: (Parameters) +# 131| 0: [Parameter] args +# 132| 4: [BlockStmt] {...} +# 133| 0: [ForStmt] for (...;...;...) ... +# 133| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 133| 0: [IntLiteral] 0 +# 133| 1: [LocalVariableAccess] access to local variable i +# 133| 0: [LTExpr] ... < ... +# 133| 0: [LocalVariableAccess] access to local variable i +# 133| 1: [PropertyCall] access to property Length +# 133| -1: [ParameterAccess] access to parameter args +# 133| 1: [PostIncrExpr] ...++ +# 133| 0: [LocalVariableAccess] access to local variable i +# 134| 2: [BlockStmt] {...} +# 135| 0: [ExprStmt] ...; +# 135| 0: [MethodCall] call to method WriteLine +# 135| -1: [TypeAccess] access to type Console +# 135| 0: [ArrayAccess] access to array element +# 135| -1: [ParameterAccess] access to parameter args +# 135| 0: [LocalVariableAccess] access to local variable i +# 140| 16: [Method] MainForeach +#-----| 2: (Parameters) +# 140| 0: [Parameter] args +# 141| 4: [BlockStmt] {...} +# 142| 0: [ForeachStmt] foreach (... ... in ...) ... +# 142| 0: [LocalVariableDeclExpr] String s +# 142| 1: [ParameterAccess] access to parameter args +# 143| 2: [BlockStmt] {...} +# 144| 0: [ExprStmt] ...; +# 144| 0: [MethodCall] call to method WriteLine +# 144| -1: [TypeAccess] access to type Console +# 144| 0: [LocalVariableAccess] access to local variable s +# 148| 17: [Method] MainBreak +# 149| 4: [BlockStmt] {...} +# 150| 0: [WhileStmt] while (...) ... +# 150| 0: [BoolLiteral] true +# 151| 1: [BlockStmt] {...} +# 152| 0: [LocalVariableDeclStmt] ... ...; +# 152| 0: [LocalVariableDeclAndInitExpr] String s = ... +# 152| 0: [MethodCall] call to method ReadLine +# 152| -1: [TypeAccess] access to type Console +# 152| 1: [LocalVariableAccess] access to local variable s +# 153| 1: [IfStmt] if (...) ... +# 153| 0: [EQExpr] ... == ... +# 153| 0: [LocalVariableAccess] access to local variable s +# 153| 1: [NullLiteral] null +# 153| 1: [BreakStmt] break; +# 154| 2: [ExprStmt] ...; +# 154| 0: [MethodCall] call to method WriteLine +# 154| -1: [TypeAccess] access to type Console +# 154| 0: [LocalVariableAccess] access to local variable s +# 158| 18: [Method] MainContinue +#-----| 2: (Parameters) +# 158| 0: [Parameter] args +# 159| 4: [BlockStmt] {...} +# 160| 0: [ForStmt] for (...;...;...) ... +# 160| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 160| 0: [IntLiteral] 0 +# 160| 1: [LocalVariableAccess] access to local variable i +# 160| 0: [LTExpr] ... < ... +# 160| 0: [LocalVariableAccess] access to local variable i +# 160| 1: [PropertyCall] access to property Length +# 160| -1: [ParameterAccess] access to parameter args +# 160| 1: [PostIncrExpr] ...++ +# 160| 0: [LocalVariableAccess] access to local variable i +# 161| 2: [BlockStmt] {...} +# 162| 0: [IfStmt] if (...) ... +# 162| 0: [MethodCall] call to method StartsWith +# 162| -1: [ArrayAccess] access to array element +# 162| -1: [ParameterAccess] access to parameter args +# 162| 0: [LocalVariableAccess] access to local variable i +# 162| 0: [StringLiteral] "/" +# 162| 1: [ContinueStmt] continue; +# 163| 1: [ExprStmt] ...; +# 163| 0: [MethodCall] call to method WriteLine +# 163| -1: [TypeAccess] access to type Console +# 163| 0: [ArrayAccess] access to array element +# 163| -1: [ParameterAccess] access to parameter args +# 163| 0: [LocalVariableAccess] access to local variable i +# 167| 19: [Method] MainGoto +#-----| 2: (Parameters) +# 167| 0: [Parameter] args +# 168| 4: [BlockStmt] {...} +# 169| 0: [LocalVariableDeclStmt] ... ...; +# 169| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 169| 0: [IntLiteral] 0 +# 169| 1: [LocalVariableAccess] access to local variable i +# 170| 1: [GotoLabelStmt] goto ...; +# 171| 2: [LabelStmt] loop: +# 171| 3: [ExprStmt] ...; +# 171| 0: [MethodCall] call to method WriteLine +# 171| -1: [TypeAccess] access to type Console +# 171| 0: [ArrayAccess] access to array element +# 171| -1: [ParameterAccess] access to parameter args +# 171| 0: [PostIncrExpr] ...++ +# 171| 0: [LocalVariableAccess] access to local variable i +# 172| 4: [LabelStmt] check: +# 172| 5: [IfStmt] if (...) ... +# 172| 0: [LTExpr] ... < ... +# 172| 0: [LocalVariableAccess] access to local variable i +# 172| 1: [PropertyCall] access to property Length +# 172| -1: [ParameterAccess] access to parameter args +# 172| 1: [GotoLabelStmt] goto ...; +# 175| 20: [Method] Add +#-----| 2: (Parameters) +# 175| 0: [Parameter] a +# 175| 1: [Parameter] b +# 176| 4: [BlockStmt] {...} +# 177| 0: [ReturnStmt] return ...; +# 177| 0: [AddExpr] ... + ... +# 177| 0: [ParameterAccess] access to parameter a +# 177| 1: [ParameterAccess] access to parameter b +# 179| 21: [Method] MainReturn +# 180| 4: [BlockStmt] {...} +# 181| 0: [ExprStmt] ...; +# 181| 0: [MethodCall] call to method WriteLine +# 181| -1: [TypeAccess] access to type Console +# 181| 0: [MethodCall] call to method Add +# 181| 0: [IntLiteral] 1 +# 181| 1: [IntLiteral] 2 +# 182| 1: [ReturnStmt] return ...; +# 185| 22: [Method] Range +#-----| 2: (Parameters) +# 185| 0: [Parameter] from +# 185| 1: [Parameter] to +# 186| 4: [BlockStmt] {...} +# 187| 0: [ForStmt] for (...;...;...) ... +# 187| -1: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 187| 0: [ParameterAccess] access to parameter from +# 187| 1: [LocalVariableAccess] access to local variable i +# 187| 0: [LTExpr] ... < ... +# 187| 0: [LocalVariableAccess] access to local variable i +# 187| 1: [ParameterAccess] access to parameter to +# 187| 1: [PostIncrExpr] ...++ +# 187| 0: [LocalVariableAccess] access to local variable i +# 188| 2: [BlockStmt] {...} +# 189| 0: [YieldReturnStmt] yield return ...; +# 189| 0: [LocalVariableAccess] access to local variable i +# 191| 1: [YieldBreakStmt] yield break; +# 193| 23: [Method] MainYield +# 194| 4: [BlockStmt] {...} +# 195| 0: [ForeachStmt] foreach (... ... in ...) ... +# 195| 0: [LocalVariableDeclExpr] Int32 x +# 195| 1: [MethodCall] call to method Range +# 195| 0: [UnaryMinusExpr] -... +# 195| 0: [IntLiteral] 10 +# 195| 1: [IntLiteral] 10 +# 196| 2: [BlockStmt] {...} +# 197| 0: [ExprStmt] ...; +# 197| 0: [MethodCall] call to method WriteLine +# 197| -1: [TypeAccess] access to type Console +# 197| 0: [LocalVariableAccess] access to local variable x +# 201| 24: [Method] Divide +#-----| 2: (Parameters) +# 201| 0: [Parameter] x +# 201| 1: [Parameter] y +# 202| 4: [BlockStmt] {...} +# 203| 0: [IfStmt] if (...) ... +# 203| 0: [EQExpr] ... == ... +# 203| 0: [ParameterAccess] access to parameter y +# 203| 1: [CastExpr] (...) ... +# 203| 0: [IntLiteral] 0 +# 203| 1: [ThrowStmt] throw ...; +# 203| 0: [ObjectCreation] object creation of type DivideByZeroException +# 204| 1: [ReturnStmt] return ...; +# 204| 0: [DivExpr] ... / ... +# 204| 0: [ParameterAccess] access to parameter x +# 204| 1: [ParameterAccess] access to parameter y +# 206| 25: [Method] MainTryThrow +#-----| 2: (Parameters) +# 206| 0: [Parameter] args +# 207| 4: [BlockStmt] {...} +# 208| 0: [TryStmt] try {...} ... +# 227| -1: [BlockStmt] {...} +# 228| 0: [ExprStmt] ...; +# 228| 0: [MethodCall] call to method WriteLine +# 228| -1: [TypeAccess] access to type Console +# 228| 0: [StringLiteral] "Good bye!" +# 209| 0: [BlockStmt] {...} +# 210| 0: [IfStmt] if (...) ... +# 210| 0: [NEExpr] ... != ... +# 210| 0: [PropertyCall] access to property Length +# 210| -1: [ParameterAccess] access to parameter args +# 210| 1: [IntLiteral] 2 +# 211| 1: [BlockStmt] {...} +# 212| 0: [ThrowStmt] throw ...; +# 212| 0: [ObjectCreation] object creation of type Exception +# 212| 0: [StringLiteral] "Two numbers required" +# 214| 1: [LocalVariableDeclStmt] ... ...; +# 214| 0: [LocalVariableDeclAndInitExpr] Double x = ... +# 214| 0: [MethodCall] call to method Parse +# 214| -1: [TypeAccess] access to type Double +# 214| 0: [ArrayAccess] access to array element +# 214| -1: [ParameterAccess] access to parameter args +# 214| 0: [IntLiteral] 0 +# 214| 1: [LocalVariableAccess] access to local variable x +# 215| 2: [LocalVariableDeclStmt] ... ...; +# 215| 0: [LocalVariableDeclAndInitExpr] Double y = ... +# 215| 0: [MethodCall] call to method Parse +# 215| -1: [TypeAccess] access to type Double +# 215| 0: [ArrayAccess] access to array element +# 215| -1: [ParameterAccess] access to parameter args +# 215| 0: [IntLiteral] 1 +# 215| 1: [LocalVariableAccess] access to local variable y +# 216| 3: [ExprStmt] ...; +# 216| 0: [MethodCall] call to method WriteLine +# 216| -1: [TypeAccess] access to type Console +# 216| 0: [MethodCall] call to method Divide +# 216| 0: [LocalVariableAccess] access to local variable x +# 216| 1: [LocalVariableAccess] access to local variable y +# 218| 1: [SpecificCatchClause] catch (...) {...} +# 218| 0: [LocalVariableDeclExpr] Exception e +# 219| 1: [BlockStmt] {...} +# 220| 0: [ExprStmt] ...; +# 220| 0: [MethodCall] call to method WriteLine +# 220| -1: [TypeAccess] access to type Console +# 220| 0: [PropertyCall] access to property Message +# 220| -1: [LocalVariableAccess] access to local variable e +# 222| 2: [GeneralCatchClause] catch {...} +# 223| 1: [BlockStmt] {...} +# 224| 0: [ExprStmt] ...; +# 224| 0: [MethodCall] call to method WriteLine +# 224| -1: [TypeAccess] access to type Console +# 224| 0: [StringLiteral] "Exception" +# 232| 26: [Method] MainCheckedUnchecked +# 233| 4: [BlockStmt] {...} +# 234| 0: [LocalVariableDeclStmt] ... ...; +# 234| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 234| 0: [MemberConstantAccess] access to constant MaxValue +# 234| -1: [TypeAccess] access to type Int32 +# 234| 1: [LocalVariableAccess] access to local variable i +# 235| 1: [CheckedStmt] checked {...} +# 236| 0: [BlockStmt] {...} +# 237| 0: [ExprStmt] ...; +# 237| 0: [MethodCall] call to method WriteLine +# 237| -1: [TypeAccess] access to type Console +# 237| 0: [AddExpr] ... + ... +# 237| 0: [LocalVariableAccess] access to local variable i +# 237| 1: [IntLiteral] 1 +# 239| 2: [UncheckedStmt] unchecked {...} +# 240| 0: [BlockStmt] {...} +# 241| 0: [ExprStmt] ...; +# 241| 0: [MethodCall] call to method WriteLine +# 241| -1: [TypeAccess] access to type Console +# 241| 0: [AddExpr] ... + ... +# 241| 0: [LocalVariableAccess] access to local variable i +# 241| 1: [IntLiteral] 1 +# 245| 27: [Class] AccountLock +# 247| 5: [Field] balance +# 248| 6: [Method] Withdraw +#-----| 2: (Parameters) +# 248| 0: [Parameter] amount +# 249| 4: [BlockStmt] {...} +# 250| 0: [LockStmt] lock (...) {...} +# 250| 0: [ThisAccess] this access +# 251| 1: [BlockStmt] {...} +# 252| 0: [IfStmt] if (...) ... +# 252| 0: [GTExpr] ... > ... +# 252| 0: [ParameterAccess] access to parameter amount +# 252| 1: [FieldAccess] access to field balance +# 253| 1: [BlockStmt] {...} +# 254| 0: [ThrowStmt] throw ...; +# 254| 0: [ObjectCreation] object creation of type Exception +# 254| 0: [StringLiteral] "Insufficient funds" +# 256| 1: [ExprStmt] ...; +# 256| 0: [AssignSubExpr] ... -= ... +# 256| 0: [ParameterAccess] access to parameter amount +# 256| 1: [FieldAccess] access to field balance +# 261| 28: [Method] MainUsing +# 262| 4: [BlockStmt] {...} +# 263| 0: [UsingBlockStmt] using (...) {...} +# 263| -1: [LocalVariableDeclAndInitExpr] TextWriter w = ... +# 263| 0: [MethodCall] call to method CreateText +# 263| -1: [TypeAccess] access to type File +# 263| 0: [StringLiteral] "test.txt" +# 263| 1: [LocalVariableAccess] access to local variable w +# 264| 1: [BlockStmt] {...} +# 265| 0: [ExprStmt] ...; +# 265| 0: [MethodCall] call to method WriteLine +# 265| -1: [LocalVariableAccess] access to local variable w +# 265| 0: [StringLiteral] "Line one" +# 266| 1: [ExprStmt] ...; +# 266| 0: [MethodCall] call to method WriteLine +# 266| -1: [LocalVariableAccess] access to local variable w +# 266| 0: [StringLiteral] "Line two" +# 267| 2: [ExprStmt] ...; +# 267| 0: [MethodCall] call to method WriteLine +# 267| -1: [LocalVariableAccess] access to local variable w +# 267| 0: [StringLiteral] "Line three" +# 269| 1: [UsingBlockStmt] using (...) {...} +# 269| 0: [MethodCall] call to method CreateText +# 269| -1: [TypeAccess] access to type File +# 269| 0: [StringLiteral] "test.txt" +# 270| 1: [BlockStmt] {...} +# 274| 29: [Method] MainLabeled +# 275| 4: [BlockStmt] {...} +# 276| 0: [GotoLabelStmt] goto ...; +# 277| 1: [LabelStmt] Label: +# 278| 2: [LocalVariableDeclStmt] ... ...; +# 278| 0: [LocalVariableDeclAndInitExpr] Int32 x = ... +# 278| 0: [IntLiteral] 23 +# 278| 1: [LocalVariableAccess] access to local variable x +# 279| 3: [ExprStmt] ...; +# 279| 0: [AssignExpr] ... = ... +# 279| 0: [IntLiteral] 9 +# 279| 1: [LocalVariableAccess] access to local variable x diff --git a/csharp/ql/test/library-tests/statements/PrintAst.qlref b/csharp/ql/test/library-tests/statements/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/statements/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/types/PrintAst.expected b/csharp/ql/test/library-tests/types/PrintAst.expected new file mode 100644 index 00000000000..db6915ac555 --- /dev/null +++ b/csharp/ql/test/library-tests/types/PrintAst.expected @@ -0,0 +1,48 @@ +types.cs: +# 1| [NamespaceDeclaration] namespace ... { ... } +# 3| 1: [Class] Class +# 5| 5: [Method] BoolType +# 6| 6: [Method] CharType +# 7| 7: [Method] DecimalType +# 8| 8: [Method] SByteType +# 9| 9: [Method] ShortType +# 10| 10: [Method] IntType +# 11| 11: [Method] LongType +# 12| 12: [Method] ByteType +# 13| 13: [Method] UShortType +# 14| 14: [Method] UIntType +# 15| 15: [Method] ULongType +# 16| 16: [Method] FloatType +# 17| 17: [Method] DoubleType +# 18| 18: [Method] NullableType +# 19| 19: [Method] VoidType +# 20| 20: [Method] ArrayType +# 21| 21: [Method] ArrayArrayType +# 22| 22: [Method] ConstructedClassType +# 23| 23: [Method] ConstructedInterfaceType +# 24| 24: [Method] ConstructedStructType +# 25| 25: [Method] DelegateType +# 26| 26: [Method] PointerType +# 27| 27: [Method] PointerPointerType +# 28| 28: [Method] Map +# 29| 29: [Method] Null +# 30| 4: [BlockStmt] {...} +# 31| 0: [ReturnStmt] return ...; +# 31| 0: [NullLiteral] null +# 34| 2: [Enum] Enum +# 37| 3: [Struct] Struct +# 40| 4: [Interface] Interface +# 43| 5: [DelegateType] Delegate +# 44| 6: [Class] GenericClass<> +#-----| 1: (Type parameters) +# 44| 0: [TypeParameter] T +# 45| 7: [Interface] GenericInterface<> +#-----| 1: (Type parameters) +# 45| 0: [TypeParameter] T +# 46| 8: [Struct] GenericStruct<> +#-----| 1: (Type parameters) +# 46| 0: [TypeParameter] T +# 47| 9: [Class] Map<,> +#-----| 1: (Type parameters) +# 47| 0: [TypeParameter] U +# 47| 1: [TypeParameter] V diff --git a/csharp/ql/test/library-tests/types/PrintAst.qlref b/csharp/ql/test/library-tests/types/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/types/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/csharp/ql/test/library-tests/unsafe/PrintAst.expected b/csharp/ql/test/library-tests/unsafe/PrintAst.expected new file mode 100644 index 00000000000..b4e9ce56c64 --- /dev/null +++ b/csharp/ql/test/library-tests/unsafe/PrintAst.expected @@ -0,0 +1,115 @@ +unsafe.cs: +# 1| [NamespaceDeclaration] namespace ... { ... } +# 3| 1: [Class] Test +# 5| 5: [Method] Main +#-----| 2: (Parameters) +# 5| 0: [Parameter] args +# 6| 4: [BlockStmt] {...} +# 7| 0: [LocalVariableDeclStmt] ... ...; +# 7| 0: [LocalVariableDeclAndInitExpr] Int32 i = ... +# 7| 0: [IntLiteral] 42 +# 7| 1: [LocalVariableAccess] access to local variable i +# 8| 1: [LocalVariableDeclStmt] ... ...; +# 8| 0: [LocalVariableDeclAndInitExpr] Int32[] ia = ... +# 8| 0: [ArrayCreation] array creation of type Int32[] +# 8| 0: [IntLiteral] 2 +# 8| 1: [LocalVariableAccess] access to local variable ia +# 9| 2: [ExprStmt] ...; +# 9| 0: [AssignExpr] ... = ... +# 9| 0: [IntLiteral] 0 +# 9| 1: [ArrayAccess] access to array element +# 9| -1: [LocalVariableAccess] access to local variable ia +# 9| 0: [IntLiteral] 0 +# 10| 3: [ExprStmt] ...; +# 10| 0: [AssignExpr] ... = ... +# 10| 0: [IntLiteral] 1 +# 10| 1: [ArrayAccess] access to array element +# 10| -1: [LocalVariableAccess] access to local variable ia +# 10| 0: [IntLiteral] 1 +# 11| 4: [LocalVariableDeclStmt] ... ...; +# 11| 0: [LocalVariableDeclAndInitExpr] Int32* ip = ... +# 11| 0: [AddressOfExpr] &... +# 11| 0: [LocalVariableAccess] access to local variable i +# 11| 1: [LocalVariableAccess] access to local variable ip +# 12| 5: [ExprStmt] ...; +# 12| 0: [AssignExpr] ... = ... +# 12| 0: [AddExpr] ... + ... +# 12| 0: [LocalVariableAccess] access to local variable ip +# 12| 1: [IntLiteral] 1 +# 12| 1: [LocalVariableAccess] access to local variable ip +# 13| 6: [ExprStmt] ...; +# 13| 0: [AssignExpr] ... = ... +# 13| 0: [AddExpr] ... + ... +# 13| 0: [PointerIndirectionExpr] *... +# 13| 0: [LocalVariableAccess] access to local variable ip +# 13| 1: [LocalVariableAccess] access to local variable ip +# 13| 1: [LocalVariableAccess] access to local variable ip +# 14| 7: [ExprStmt] ...; +# 14| 0: [AssignExpr] ... = ... +# 14| 0: [AddExpr] ... + ... +# 14| 0: [PointerIndirectionExpr] *... +# 14| 0: [LocalVariableAccess] access to local variable ip +# 14| 1: [AddressOfExpr] &... +# 14| 0: [LocalVariableAccess] access to local variable i +# 14| 1: [LocalVariableAccess] access to local variable ip +# 15| 8: [LocalVariableDeclStmt] ... ...; +# 15| 0: [LocalVariableDeclAndInitExpr] Int32* ip42 = ... +# 15| 0: [AddressOfExpr] &... +# 15| 0: [LocalVariableAccess] access to local variable i +# 15| 1: [LocalVariableAccess] access to local variable ip42 +# 16| 9: [ExprStmt] ...; +# 16| 0: [PostIncrExpr] ...++ +# 16| 0: [LocalVariableAccess] access to local variable ip +# 17| 10: [ExprStmt] ...; +# 17| 0: [AssignExpr] ... = ... +# 17| 0: [SubExpr] ... - ... +# 17| 0: [LocalVariableAccess] access to local variable ip +# 17| 1: [IntLiteral] 1 +# 17| 1: [LocalVariableAccess] access to local variable ip +# 18| 11: [ExprStmt] ...; +# 18| 0: [AssignExpr] ... = ... +# 18| 0: [SizeofExpr] sizeof(..) +# 18| 0: [TypeAccess] access to type Char* +# 18| 1: [PointerIndirectionExpr] *... +# 18| 0: [LocalVariableAccess] access to local variable ip42 +# 19| 12: [LocalVariableDeclStmt] ... ...; +# 19| 0: [LocalVariableDeclAndInitExpr] Int64 distance = ... +# 19| 0: [SubExpr] ... - ... +# 19| 0: [LocalVariableAccess] access to local variable ip +# 19| 1: [LocalVariableAccess] access to local variable ip42 +# 19| 1: [LocalVariableAccess] access to local variable distance +# 22| 6: [Method] f +#-----| 2: (Parameters) +# 22| 0: [Parameter] p +# 23| 4: [BlockStmt] {...} +# 24| 0: [ExprStmt] ...; +# 24| 0: [MethodCall] call to method ToString +# 24| -1: [PointerIndirectionExpr] *... +# 24| 0: [ParameterAccess] access to parameter p +# 25| 1: [ExprStmt] ...; +# 25| 0: [MethodCall] call to method ToString +# 25| -1: [PointerIndirectionExpr] *... +# 25| 0: [ParameterAccess] access to parameter p +# 26| 2: [ExprStmt] ...; +# 26| 0: [MethodCall] call to method ToString +# 26| -1: [PointerIndirectionExpr] *... +# 26| 0: [AddExpr] ... + ... +# 26| 0: [ParameterAccess] access to parameter p +# 26| 1: [IntLiteral] 0 +# 30| 7: [Method] g +# 30| 4: [BlockStmt] {...} +# 32| 8: [Method] h +# 33| 4: [BlockStmt] {...} +# 34| 0: [UnsafeStmt] unsafe {...} +# 35| 0: [BlockStmt] {...} +# 36| 0: [LocalVariableDeclStmt] ... ...; +# 36| 0: [LocalVariableDeclAndInitExpr] Int32[] data = ... +# 36| 0: [ArrayCreation] array creation of type Int32[] +# 36| 0: [IntLiteral] 10 +# 36| 1: [LocalVariableAccess] access to local variable data +# 37| 1: [FixedStmt] fixed(...) { ... } +# 37| -1: [LocalVariableDeclAndInitExpr] Int32* p = ... +# 37| 0: [LocalVariableAccess] access to local variable data +# 37| 1: [LocalVariableAccess] access to local variable p +# 38| 0: [BlockStmt] {...} +# 44| 2: [Class] SafeClass diff --git a/csharp/ql/test/library-tests/unsafe/PrintAst.qlref b/csharp/ql/test/library-tests/unsafe/PrintAst.qlref new file mode 100644 index 00000000000..15af8b109dd --- /dev/null +++ b/csharp/ql/test/library-tests/unsafe/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/csharp/PrintAst.ql \ No newline at end of file diff --git a/docs/ql-libraries/dataflow/dataflow.md b/docs/ql-libraries/dataflow/dataflow.md index 3686b3ed4a4..46ba27acccf 100644 --- a/docs/ql-libraries/dataflow/dataflow.md +++ b/docs/ql-libraries/dataflow/dataflow.md @@ -98,6 +98,10 @@ Recommendations: also work, but the upside of `use-use` steps is that sources defined in terms of variable reads just work out of the box. It also makes certain barrier-implementations simpler. +* A predicate `DataFlowCallable Node::getEnclosingCallable()` is required, and in + order to ensure appropriate join-orders, it is important that the QL compiler knows + that this predicate is functional. It can therefore be necessary to enclose the body + of this predicate in a `unique` aggregate. The shared library does not use `localFlowStep` nor `localFlow` but users of `DataFlow.qll` may expect the existence of `DataFlow::localFlowStep` and diff --git a/java/ql/src/semmle/code/java/Expr.qll b/java/ql/src/semmle/code/java/Expr.qll index 63fc61bf1aa..cb3fcae1873 100755 --- a/java/ql/src/semmle/code/java/Expr.qll +++ b/java/ql/src/semmle/code/java/Expr.qll @@ -1344,10 +1344,7 @@ class VarAccess extends Expr, @varaccess { */ predicate isLValue() { exists(Assignment a | a.getDest() = this) or - exists(PreIncExpr e | e.getExpr() = this) or - exists(PreDecExpr e | e.getExpr() = this) or - exists(PostIncExpr e | e.getExpr() = this) or - exists(PostDecExpr e | e.getExpr() = this) + exists(UnaryAssignExpr e | e.getExpr() = this) } /** diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 5042dce683f..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -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() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -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() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 5042dce683f..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -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() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 5042dce683f..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -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() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 5042dce683f..8c210edbe5f 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -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() } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -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 + ")") } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll index b6ca8986307..ceeb4d64064 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll @@ -78,15 +78,19 @@ class Node extends TNode { result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getType() } - /** Gets the callable in which this node occurs. */ - Callable getEnclosingCallable() { + private Callable getEnclosingCallableImpl() { result = this.asExpr().getEnclosingCallable() or result = this.asParameter().getCallable() or result = this.(ImplicitVarargsArray).getCall().getEnclosingCallable() or result = this.(InstanceParameterNode).getCallable() or result = this.(ImplicitInstanceAccess).getInstanceAccess().getEnclosingCallable() or result = this.(MallocNode).getClassInstanceExpr().getEnclosingCallable() or - result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getEnclosingCallable() + result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getEnclosingCallableImpl() + } + + /** Gets the callable in which this node occurs. */ + Callable getEnclosingCallable() { + result = unique(DataFlowCallable c | c = this.getEnclosingCallableImpl() | c) } private Type getImprovedTypeBound() { diff --git a/java/ql/src/semmle/code/java/frameworks/jOOQ.qll b/java/ql/src/semmle/code/java/frameworks/jOOQ.qll new file mode 100644 index 00000000000..5f473a18f33 --- /dev/null +++ b/java/ql/src/semmle/code/java/frameworks/jOOQ.qll @@ -0,0 +1,23 @@ +/** + * Provides classes and predicates for working with the jOOQ framework. + */ + +import java + +/** + * Methods annotated with this allow for generation of "plain SQL" + * and is prone to SQL injection. + * https://www.jooq.org/doc/current/manual/sql-building/plain-sql/ + */ +private class PlainSQLType extends Annotation { + PlainSQLType() { this.getType().hasQualifiedName("org.jooq", "PlainSQL") } +} + +/** + * Holds if `m` is a jOOQ SQL method taking an SQL string as its + * first argument. + */ +predicate jOOQSqlMethod(Method m) { + m.getAnAnnotation() instanceof PlainSQLType and + m.getParameterType(0) instanceof TypeString +} diff --git a/java/ql/src/semmle/code/java/security/QueryInjection.qll b/java/ql/src/semmle/code/java/security/QueryInjection.qll index 6eb4858519a..a81e19a2c28 100644 --- a/java/ql/src/semmle/code/java/security/QueryInjection.qll +++ b/java/ql/src/semmle/code/java/security/QueryInjection.qll @@ -3,6 +3,7 @@ import java import semmle.code.java.dataflow.DataFlow import semmle.code.java.frameworks.Jdbc +import semmle.code.java.frameworks.jOOQ import semmle.code.java.frameworks.android.SQLite import semmle.code.java.frameworks.javaee.Persistence import semmle.code.java.frameworks.SpringJdbc @@ -30,6 +31,8 @@ private class SqlInjectionSink extends QueryInjectionSink { index = 0 and mybatisSqlMethod(m) or index = 0 and hibernateSqlMethod(m) + or + index = 0 and jOOQSqlMethod(m) ) } } diff --git a/java/ql/src/semmle/code/java/security/XSS.qll b/java/ql/src/semmle/code/java/security/XSS.qll index 9f5ed3fe9d6..fd1fdcde061 100644 --- a/java/ql/src/semmle/code/java/security/XSS.qll +++ b/java/ql/src/semmle/code/java/security/XSS.qll @@ -97,6 +97,7 @@ class WritingMethod extends Method { ( this.getName().matches("print%") or this.getName() = "append" or + this.getName() = "format" or this.getName() = "write" ) } diff --git a/java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.expected similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.expected rename to java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.expected diff --git a/java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.java b/java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.java similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.java rename to java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.java diff --git a/java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.qlref b/java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.qlref similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-074/JndiInjection.qlref rename to java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/JndiInjection.qlref diff --git a/java/ql/test/experimental/query-tests/security/CWE-074/options b/java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/options similarity index 100% rename from java/ql/test/experimental/query-tests/security/CWE-074/options rename to java/ql/test/experimental/query-tests/security/CWE-074-JndiInjection/options diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index 8dcc6d3a5c5..9e90fddfc85 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -669,7 +669,9 @@ public class ASTExtractor { public Label visit(Program nd, Context c) { contextManager.enterContainer(toplevelLabel); - isStrict = hasUseStrict(nd.getBody()); + boolean prevIsStrict = isStrict; + + isStrict = isStrict || hasUseStrict(nd.getBody()); // Add platform-specific globals. scopeManager.addVariables(platform.getPredefinedGlobals()); @@ -715,6 +717,8 @@ public class ASTExtractor { emitNodeSymbol(nd, toplevelLabel); + isStrict = prevIsStrict; + return toplevelLabel; } diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 66cb57ba30f..28c96f806f7 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -144,7 +144,7 @@ import com.semmle.util.trap.TrapWriter; * *
    *
  • All JavaScript files, that is, files with one of the extensions supported by {@link - * FileType#JS} (currently ".js", ".jsx", ".mjs", ".es6", ".es"). + * FileType#JS} (currently ".js", ".jsx", ".mjs", ".cjs", ".es6", ".es"). *
  • All HTML files, that is, files with with one of the extensions supported by {@link * FileType#HTML} (currently ".htm", ".html", ".xhtm", ".xhtml", ".vue"). *
  • All YAML files, that is, files with one of the extensions supported by {@link @@ -210,6 +210,7 @@ public class AutoBuild { private final String defaultEncoding; private ExecutorService threadPool; private volatile boolean seenCode = false; + private volatile boolean seenFiles = false; private boolean installDependencies = false; private int installDependenciesTimeout; private final VirtualSourceRoot virtualSourceRoot; @@ -472,7 +473,11 @@ public class AutoBuild { shutdownThreadPool(); } if (!seenCode) { - warn("No JavaScript or TypeScript code found."); + if (seenFiles) { + warn("Only found JavaScript or TypeScript files that were empty or contained syntax errors."); + } else { + warn("No JavaScript or TypeScript code found."); + } return -1; } return 0; @@ -1201,6 +1206,7 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set long start = logBeginProcess("Extracting " + file); Integer loc = extractor.extract(f, state); if (!extractor.getConfig().isExterns() && (loc == null || loc != 0)) seenCode = true; + if (!extractor.getConfig().isExterns()) seenFiles = true; logEndProcess(start, "Done extracting " + file); } catch (Throwable t) { System.err.println("Exception while extracting " + file + "."); diff --git a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java index 4c36e860696..cea66cac21a 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java @@ -116,7 +116,7 @@ public class FileExtractor { } }, - JS(".js", ".jsx", ".mjs", ".es6", ".es") { + JS(".js", ".jsx", ".mjs", ".cjs", ".es6", ".es") { @Override public IExtractor mkExtractor(ExtractorConfig config, ExtractorState state) { return new ScriptExtractor(config); diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java index 197a3473a65..e3c601aaaad 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScriptExtractor.java @@ -19,6 +19,11 @@ public class ScriptExtractor implements IExtractor { return extension.equals(".mjs") || extension.equals(".es6") || extension.equals(".es"); } + /** True if files with the given extension should always be treated as CommonJS modules. */ + private boolean isAlwaysCommonJSModule(String extension) { + return extension.equals(".cjs"); + } + @Override public LoCInfo extract(TextualExtractor textualExtractor) { LocationManager locationManager = textualExtractor.getLocationManager(); @@ -45,9 +50,13 @@ public class ScriptExtractor implements IExtractor { } // Some file extensions are interpreted as modules by default. - if (isAlwaysModule(locationManager.getSourceFileExtension())) { - if (config.getSourceType() == SourceType.AUTO) + if (config.getSourceType() == SourceType.AUTO) { + if (isAlwaysModule(locationManager.getSourceFileExtension())) { config = config.withSourceType(SourceType.MODULE); + } + if (isAlwaysCommonJSModule(locationManager.getSourceFileExtension())) { + config = config.withSourceType(SourceType.COMMONJS_MODULE); + } } ScopeManager scopeManager = diff --git a/javascript/extractor/tests/extensions/input/tst4.cjs b/javascript/extractor/tests/extensions/input/tst4.cjs new file mode 100644 index 00000000000..a552cea0167 --- /dev/null +++ b/javascript/extractor/tests/extensions/input/tst4.cjs @@ -0,0 +1 @@ +console.log("Hello CommonJS"); diff --git a/javascript/extractor/tests/extensions/output/trap/tst4.cjs.trap b/javascript/extractor/tests/extensions/output/trap/tst4.cjs.trap new file mode 100644 index 00000000000..5f76c8832f9 --- /dev/null +++ b/javascript/extractor/tests/extensions/output/trap/tst4.cjs.trap @@ -0,0 +1,141 @@ +#10000=@"/tst4.cjs;sourcefile" +files(#10000,"/tst4.cjs","tst4","cjs",0) +#10001=@"/;folder" +folders(#10001,"/","") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=@"global_scope" +scopes(#20000,0) +#20001=@"script;{#10000},1,1" +#20002=* +lines(#20002,#20001,"console.log(""Hello CommonJS"");"," +") +#20003=@"loc,{#10000},1,1,1,30" +locations_default(#20003,#10000,1,1,1,30) +hasLocation(#20002,#20003) +numlines(#20001,1,1,0) +#20004=* +tokeninfo(#20004,6,#20001,0,"console") +#20005=@"loc,{#10000},1,1,1,7" +locations_default(#20005,#10000,1,1,1,7) +hasLocation(#20004,#20005) +#20006=* +tokeninfo(#20006,8,#20001,1,".") +#20007=@"loc,{#10000},1,8,1,8" +locations_default(#20007,#10000,1,8,1,8) +hasLocation(#20006,#20007) +#20008=* +tokeninfo(#20008,6,#20001,2,"log") +#20009=@"loc,{#10000},1,9,1,11" +locations_default(#20009,#10000,1,9,1,11) +hasLocation(#20008,#20009) +#20010=* +tokeninfo(#20010,8,#20001,3,"(") +#20011=@"loc,{#10000},1,12,1,12" +locations_default(#20011,#10000,1,12,1,12) +hasLocation(#20010,#20011) +#20012=* +tokeninfo(#20012,4,#20001,4,"""Hello CommonJS""") +#20013=@"loc,{#10000},1,13,1,28" +locations_default(#20013,#10000,1,13,1,28) +hasLocation(#20012,#20013) +#20014=* +tokeninfo(#20014,8,#20001,5,")") +#20015=@"loc,{#10000},1,29,1,29" +locations_default(#20015,#10000,1,29,1,29) +hasLocation(#20014,#20015) +#20016=* +tokeninfo(#20016,8,#20001,6,";") +#20017=@"loc,{#10000},1,30,1,30" +locations_default(#20017,#10000,1,30,1,30) +hasLocation(#20016,#20017) +#20018=* +tokeninfo(#20018,0,#20001,7,"") +#20019=@"loc,{#10000},2,1,2,0" +locations_default(#20019,#10000,2,1,2,0) +hasLocation(#20018,#20019) +toplevels(#20001,0) +#20020=@"loc,{#10000},1,1,2,0" +locations_default(#20020,#10000,1,1,2,0) +hasLocation(#20001,#20020) +#20021=@"module;{#10000},1,1" +scopes(#20021,3) +scopenodes(#20001,#20021) +scopenesting(#20021,#20000) +#20022=@"var;{require};{#20021}" +variables(#20022,"require",#20021) +#20023=@"var;{module};{#20021}" +variables(#20023,"module",#20021) +#20024=@"var;{exports};{#20021}" +variables(#20024,"exports",#20021) +#20025=@"var;{__filename};{#20021}" +variables(#20025,"__filename",#20021) +#20026=@"var;{__dirname};{#20021}" +variables(#20026,"__dirname",#20021) +#20027=@"var;{arguments};{#20021}" +variables(#20027,"arguments",#20021) +isModule(#20001) +#20028=* +stmts(#20028,2,#20001,0,"console ... onJS"");") +hasLocation(#20028,#20003) +stmtContainers(#20028,#20001) +#20029=* +exprs(#20029,13,#20028,0,"console ... monJS"")") +#20030=@"loc,{#10000},1,1,1,29" +locations_default(#20030,#10000,1,1,1,29) +hasLocation(#20029,#20030) +enclosingStmt(#20029,#20028) +exprContainers(#20029,#20001) +#20031=* +exprs(#20031,14,#20029,-1,"console.log") +#20032=@"loc,{#10000},1,1,1,11" +locations_default(#20032,#10000,1,1,1,11) +hasLocation(#20031,#20032) +enclosingStmt(#20031,#20028) +exprContainers(#20031,#20001) +#20033=* +exprs(#20033,79,#20031,0,"console") +hasLocation(#20033,#20005) +enclosingStmt(#20033,#20028) +exprContainers(#20033,#20001) +literals("console","console",#20033) +#20034=@"var;{console};{#20000}" +variables(#20034,"console",#20000) +bind(#20033,#20034) +#20035=* +exprs(#20035,0,#20031,1,"log") +hasLocation(#20035,#20009) +enclosingStmt(#20035,#20028) +exprContainers(#20035,#20001) +literals("log","log",#20035) +#20036=* +exprs(#20036,4,#20029,0,"""Hello CommonJS""") +hasLocation(#20036,#20013) +enclosingStmt(#20036,#20028) +exprContainers(#20036,#20001) +literals("Hello CommonJS","""Hello CommonJS""",#20036) +#20037=* +regexpterm(#20037,14,#20036,0,"Hello CommonJS") +#20038=@"loc,{#10000},1,14,1,27" +locations_default(#20038,#10000,1,14,1,27) +hasLocation(#20037,#20038) +regexpConstValue(#20037,"Hello CommonJS") +#20039=* +entry_cfg_node(#20039,#20001) +#20040=@"loc,{#10000},1,1,1,0" +locations_default(#20040,#10000,1,1,1,0) +hasLocation(#20039,#20040) +#20041=* +exit_cfg_node(#20041,#20001) +hasLocation(#20041,#20019) +successor(#20028,#20033) +successor(#20036,#20029) +successor(#20035,#20031) +successor(#20033,#20035) +successor(#20031,#20036) +successor(#20029,#20041) +successor(#20039,#20028) +numlines(#10000,1,1,0) +filetype(#10000,"javascript") diff --git a/javascript/extractor/tests/ts/output/trap/decorators.ts.trap b/javascript/extractor/tests/ts/output/trap/decorators.ts.trap index 58ee0098c30..56a829b2cfc 100644 --- a/javascript/extractor/tests/ts/output/trap/decorators.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/decorators.ts.trap @@ -311,10 +311,10 @@ scopenodes(#20001,#20112) scopenesting(#20112,#20000) isModule(#20001) isES2015Module(#20001) -#20113=@"var;{fun};{#20112}" -variables(#20113,"fun",#20112) -#20114=@"var;{Class};{#20112}" -variables(#20114,"Class",#20112) +#20113=@"var;{Class};{#20112}" +variables(#20113,"Class",#20112) +#20114=@"var;{fun};{#20112}" +variables(#20114,"fun",#20112) #20115=@"var;{Class2};{#20112}" variables(#20115,"Class2",#20112) #20116=@"local_type_name;{Class};{#20112}" @@ -347,7 +347,7 @@ hasLocation(#20123,#20037) enclosingStmt(#20123,#20118) exprContainers(#20123,#20001) literals("Class","Class",#20123) -decl(#20123,#20114) +decl(#20123,#20113) typedecl(#20123,#20116) #20124=* scopes(#20124,10) @@ -499,7 +499,7 @@ exprs(#20161,78,#20159,-1,"fun") hasLocation(#20161,#20086) exprContainers(#20161,#20159) literals("fun","fun",#20161) -decl(#20161,#20113) +decl(#20161,#20114) #20162=* scopes(#20162,1) scopenodes(#20159,#20162) diff --git a/javascript/extractor/tests/ts/output/trap/export.ts.trap b/javascript/extractor/tests/ts/output/trap/export.ts.trap index fe88825fc6a..34ef992309d 100644 --- a/javascript/extractor/tests/ts/output/trap/export.ts.trap +++ b/javascript/extractor/tests/ts/output/trap/export.ts.trap @@ -155,12 +155,12 @@ scopenodes(#20001,#20055) scopenesting(#20055,#20000) isModule(#20001) isES2015Module(#20001) -#20056=@"var;{f};{#20055}" -variables(#20056,"f",#20055) -#20057=@"var;{foo};{#20055}" -variables(#20057,"foo",#20055) -#20058=@"var;{C};{#20055}" -variables(#20058,"C",#20055) +#20056=@"var;{foo};{#20055}" +variables(#20056,"foo",#20055) +#20057=@"var;{C};{#20055}" +variables(#20057,"C",#20055) +#20058=@"var;{f};{#20055}" +variables(#20058,"f",#20055) #20059=@"local_type_name;{C};{#20055}" local_type_names(#20059,"C",#20055) #20060=* @@ -186,7 +186,7 @@ hasLocation(#20065,#20017) enclosingStmt(#20065,#20061) exprContainers(#20065,#20001) literals("foo","foo",#20065) -decl(#20065,#20057) +decl(#20065,#20056) #20066=* exprs(#20066,3,#20063,1,"42") hasLocation(#20066,#20021) @@ -209,7 +209,7 @@ hasLocation(#20070,#20029) enclosingStmt(#20070,#20068) exprContainers(#20070,#20001) literals("C","C",#20070) -decl(#20070,#20058) +decl(#20070,#20057) typedecl(#20070,#20059) #20071=* scopes(#20071,10) @@ -260,7 +260,7 @@ exprs(#20083,78,#20081,-1,"f") hasLocation(#20083,#20041) exprContainers(#20083,#20081) literals("f","f",#20083) -decl(#20083,#20056) +decl(#20083,#20058) #20084=* scopes(#20084,1) scopenodes(#20081,#20084) diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql index 14115853640..09aad31c96d 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql @@ -43,6 +43,10 @@ where or // target is a HTTP URL to a domain on any TLD target.regexpMatch("(?i)https?://([a-z0-9-]+\\.)+([a-z]+)(:[0-9]+)?/?") + or + // target is a HTTP URL to a domain on any TLD with path elements, and the check is an includes check + check instanceof StringOps::Includes and + target.regexpMatch("(?i)https?://([a-z0-9-]+\\.)+([a-z]+)(:[0-9]+)?/[a-z0-9/_-]+") ) and ( if check instanceof StringOps::StartsWith diff --git a/javascript/ql/src/semmle/javascript/NodeJS.qll b/javascript/ql/src/semmle/javascript/NodeJS.qll index 6da4a625537..43fbb256998 100644 --- a/javascript/ql/src/semmle/javascript/NodeJS.qll +++ b/javascript/ql/src/semmle/javascript/NodeJS.qll @@ -221,7 +221,7 @@ class Require extends CallExpr, Import { * *
      *
    • the file `c/p`; - *
    • the file `c/p.{tsx,ts,jsx,es6,es,mjs}`; + *
    • the file `c/p.{tsx,ts,jsx,es6,es,mjs,cjs}`; *
    • the file `c/p.js`; *
    • the file `c/p.json`; *
    • the file `c/p.node`; @@ -230,12 +230,12 @@ class Require extends CallExpr, Import { *
    • if `c/p/package.json` exists and specifies a `main` module `m`: *
        *
      • the file `c/p/m`; - *
      • the file `c/p/m.{tsx,ts,jsx,es6,es,mjs}`; + *
      • the file `c/p/m.{tsx,ts,jsx,es6,es,mjs,cjs}`; *
      • the file `c/p/m.js`; *
      • the file `c/p/m.json`; *
      • the file `c/p/m.node`; *
      - *
    • the file `c/p/index.{tsx,ts,jsx,es6,es,mjs}`; + *
    • the file `c/p/index.{tsx,ts,jsx,es6,es,mjs,cjs}`; *
    • the file `c/p/index.js`; *
    • the file `c/p/index.json`; *
    • the file `c/p/index.node`. diff --git a/javascript/ql/src/semmle/javascript/NodeModuleResolutionImpl.qll b/javascript/ql/src/semmle/javascript/NodeModuleResolutionImpl.qll index 8eecf46c617..01b01f1ac04 100644 --- a/javascript/ql/src/semmle/javascript/NodeModuleResolutionImpl.qll +++ b/javascript/ql/src/semmle/javascript/NodeModuleResolutionImpl.qll @@ -26,11 +26,13 @@ int getFileExtensionPriority(string ext) { or ext = "mjs" and result = 5 or - ext = "js" and result = 6 + ext = "cjs" and result = 6 or - ext = "json" and result = 7 + ext = "js" and result = 7 or - ext = "node" and result = 8 + ext = "json" and result = 8 + or + ext = "node" and result = 9 } int prioritiesPerCandidate() { result = 3 * (numberOfExtensions() + 1) } diff --git a/javascript/ql/test/library-tests/CallGraphs/FullTest/non-strict.js b/javascript/ql/test/library-tests/CallGraphs/FullTest/non-strict.js new file mode 100644 index 00000000000..eb6e20279ea --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/FullTest/non-strict.js @@ -0,0 +1,8 @@ +(function () { + if (true) { + function foo() { + return 3; + } + } + return foo(); // this resolves to `foo` above, because we have function-scope in non-strict mode. +})(); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CallGraphs/FullTest/strict.js b/javascript/ql/test/library-tests/CallGraphs/FullTest/strict.js new file mode 100644 index 00000000000..f3f949d1727 --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/FullTest/strict.js @@ -0,0 +1,10 @@ +(function () { + if (true) { + function foo() { + return 3; + } + } + return foo(); // `foo` is not defined, because we are in strict-mode. +})(); + +export default 3; // strict-mode implied because ES2015 module. \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CallGraphs/FullTest/strict2.js b/javascript/ql/test/library-tests/CallGraphs/FullTest/strict2.js new file mode 100644 index 00000000000..a499b5c5a7f --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/FullTest/strict2.js @@ -0,0 +1,12 @@ +"use strict"; +(function () { + "use strict"; + if (true) { + function foo() { + return 3; + } + } + return foo(); // `foo` is not defined, because we are in strict-mode. +})(); + +export default 3; // strict-mode implied because ES2015 module. \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected b/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected index 90d47a02286..86cd32e4178 100644 --- a/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected +++ b/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected @@ -90,6 +90,11 @@ test_getAFunctionValue | m.js:3:1:3:16 | module.exports.f | m.js:1:13:1:25 | function() {} | | n.js:2:1:2:3 | m.f | m.js:1:13:1:25 | function() {} | | n.js:5:1:5:4 | m2.f | m2.js:2:6:2:18 | function() {} | +| non-strict.js:1:1:8:2 | (functi ... ode.\\n}) | non-strict.js:1:2:8:1 | functio ... mode.\\n} | +| non-strict.js:1:2:8:1 | functio ... mode.\\n} | non-strict.js:1:2:8:1 | functio ... mode.\\n} | +| non-strict.js:3:5:5:5 | functio ... ;\\n } | non-strict.js:3:5:5:5 | functio ... ;\\n } | +| non-strict.js:3:14:3:16 | foo | non-strict.js:3:5:5:5 | functio ... ;\\n } | +| non-strict.js:7:10:7:12 | foo | non-strict.js:3:5:5:5 | functio ... ;\\n } | | protoclass.js:3:1:5:1 | functio ... it();\\n} | protoclass.js:3:1:5:1 | functio ... it();\\n} | | protoclass.js:3:10:3:10 | F | protoclass.js:3:1:5:1 | functio ... it();\\n} | | protoclass.js:4:3:4:11 | this.init | protoclass.js:7:20:11:1 | functio ... m();\\n} | @@ -110,6 +115,12 @@ test_getAFunctionValue | reflection.js:7:1:7:3 | add | reflection.js:1:1:3:1 | functio ... x+y;\\n} | | reflection.js:8:1:8:3 | add | reflection.js:1:1:3:1 | functio ... x+y;\\n} | | reflection.js:8:1:8:9 | add.apply | reflection.js:5:15:5:39 | functio ... n 56; } | +| strict2.js:2:1:10:2 | (functi ... ode.\\n}) | strict2.js:2:2:10:1 | functio ... mode.\\n} | +| strict2.js:2:2:10:1 | functio ... mode.\\n} | strict2.js:2:2:10:1 | functio ... mode.\\n} | +| strict2.js:5:5:7:5 | functio ... ;\\n } | strict2.js:5:5:7:5 | functio ... ;\\n } | +| strict.js:1:1:8:2 | (functi ... ode.\\n}) | strict.js:1:2:8:1 | functio ... mode.\\n} | +| strict.js:1:2:8:1 | functio ... mode.\\n} | strict.js:1:2:8:1 | functio ... mode.\\n} | +| strict.js:3:5:5:5 | functio ... ;\\n } | strict.js:3:5:5:5 | functio ... ;\\n } | | tst3.js:1:1:1:22 | functio ... fn() {} | tst3.js:1:1:1:22 | functio ... fn() {} | | tst3.js:2:1:2:23 | functio ... n2() {} | tst3.js:2:1:2:23 | functio ... n2() {} | | tst.js:1:1:1:15 | function f() {} | tst.js:1:1:1:15 | function f() {} | @@ -225,6 +236,8 @@ test_getNumArgument | n.js:2:1:2:5 | m.f() | 0 | | n.js:4:10:4:24 | require('./m2') | 1 | | n.js:5:1:5:6 | m2.f() | 0 | +| non-strict.js:1:1:8:4 | (functi ... e.\\n})() | 0 | +| non-strict.js:7:10:7:14 | foo() | 0 | | protoclass.js:4:3:4:13 | this.init() | 0 | | protoclass.js:8:3:8:15 | this.method() | 0 | | protoclass.js:9:11:9:32 | this.me ... d(this) | 1 | @@ -233,6 +246,10 @@ test_getNumArgument | reflection.js:7:1:7:22 | add.cal ... 23, 19) | 3 | | reflection.js:7:1:7:22 | reflective call | 2 | | reflection.js:8:1:8:25 | add.app ... 3, 19]) | 2 | +| strict2.js:2:1:10:4 | (functi ... e.\\n})() | 0 | +| strict2.js:9:10:9:14 | foo() | 0 | +| strict.js:1:1:8:4 | (functi ... e.\\n})() | 0 | +| strict.js:7:10:7:14 | foo() | 0 | | tst.js:6:1:6:3 | f() | 0 | | tst.js:7:1:7:3 | g() | 0 | | tst.js:8:1:8:3 | h() | 0 | @@ -321,6 +338,8 @@ test_getCalleeNode | n.js:2:1:2:5 | m.f() | n.js:2:1:2:3 | m.f | | n.js:4:10:4:24 | require('./m2') | n.js:4:10:4:16 | require | | n.js:5:1:5:6 | m2.f() | n.js:5:1:5:4 | m2.f | +| non-strict.js:1:1:8:4 | (functi ... e.\\n})() | non-strict.js:1:1:8:2 | (functi ... ode.\\n}) | +| non-strict.js:7:10:7:14 | foo() | non-strict.js:7:10:7:12 | foo | | protoclass.js:4:3:4:13 | this.init() | protoclass.js:4:3:4:11 | this.init | | protoclass.js:8:3:8:15 | this.method() | protoclass.js:8:3:8:13 | this.method | | protoclass.js:9:11:9:32 | this.me ... d(this) | protoclass.js:9:11:9:26 | this.method.bind | @@ -330,6 +349,10 @@ test_getCalleeNode | reflection.js:7:1:7:22 | reflective call | reflection.js:7:1:7:3 | add | | reflection.js:8:1:8:25 | add.app ... 3, 19]) | reflection.js:8:1:8:9 | add.apply | | reflection.js:8:1:8:25 | reflective call | reflection.js:8:1:8:3 | add | +| strict2.js:2:1:10:4 | (functi ... e.\\n})() | strict2.js:2:1:10:2 | (functi ... ode.\\n}) | +| strict2.js:9:10:9:14 | foo() | strict2.js:9:10:9:12 | foo | +| strict.js:1:1:8:4 | (functi ... e.\\n})() | strict.js:1:1:8:2 | (functi ... ode.\\n}) | +| strict.js:7:10:7:14 | foo() | strict.js:7:10:7:12 | foo | | tst.js:6:1:6:3 | f() | tst.js:6:1:6:1 | f | | tst.js:7:1:7:3 | g() | tst.js:7:1:7:1 | g | | tst.js:8:1:8:3 | h() | tst.js:8:1:8:1 | h | @@ -408,11 +431,15 @@ test_getACallee | m.js:3:1:3:18 | module.exports.f() | m.js:1:13:1:25 | function() {} | | n.js:2:1:2:5 | m.f() | m.js:1:13:1:25 | function() {} | | n.js:5:1:5:6 | m2.f() | m2.js:2:6:2:18 | function() {} | +| non-strict.js:1:1:8:4 | (functi ... e.\\n})() | non-strict.js:1:2:8:1 | functio ... mode.\\n} | +| non-strict.js:7:10:7:14 | foo() | non-strict.js:3:5:5:5 | functio ... ;\\n } | | protoclass.js:4:3:4:13 | this.init() | protoclass.js:7:20:11:1 | functio ... m();\\n} | | protoclass.js:8:3:8:15 | this.method() | protoclass.js:13:22:13:34 | function() {} | | reflection.js:7:1:7:22 | reflective call | reflection.js:1:1:3:1 | functio ... x+y;\\n} | | reflection.js:8:1:8:25 | add.app ... 3, 19]) | reflection.js:5:15:5:39 | functio ... n 56; } | | reflection.js:8:1:8:25 | reflective call | reflection.js:1:1:3:1 | functio ... x+y;\\n} | +| strict2.js:2:1:10:4 | (functi ... e.\\n})() | strict2.js:2:2:10:1 | functio ... mode.\\n} | +| strict.js:1:1:8:4 | (functi ... e.\\n})() | strict.js:1:2:8:1 | functio ... mode.\\n} | | tst.js:6:1:6:3 | f() | tst.js:1:1:1:15 | function f() {} | | tst.js:7:1:7:3 | g() | tst.js:2:9:2:21 | function() {} | | tst.js:8:1:8:3 | h() | tst.js:3:5:3:17 | function() {} | @@ -463,6 +490,7 @@ test_getCalleeName | n.js:2:1:2:5 | m.f() | f | | n.js:4:10:4:24 | require('./m2') | require | | n.js:5:1:5:6 | m2.f() | f | +| non-strict.js:7:10:7:14 | foo() | foo | | protoclass.js:4:3:4:13 | this.init() | init | | protoclass.js:8:3:8:15 | this.method() | method | | protoclass.js:9:11:9:32 | this.me ... d(this) | bind | @@ -470,6 +498,8 @@ test_getCalleeName | reflection.js:4:5:4:12 | sneaky() | sneaky | | reflection.js:7:1:7:22 | add.cal ... 23, 19) | call | | reflection.js:8:1:8:25 | add.app ... 3, 19]) | apply | +| strict2.js:9:10:9:14 | foo() | foo | +| strict.js:7:10:7:14 | foo() | foo | | tst.js:6:1:6:3 | f() | f | | tst.js:7:1:7:3 | g() | g | | tst.js:8:1:8:3 | h() | h | diff --git a/javascript/ql/test/library-tests/ModuleTypes/commonjs.cjs b/javascript/ql/test/library-tests/ModuleTypes/commonjs.cjs new file mode 100644 index 00000000000..344893b298a --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/commonjs.cjs @@ -0,0 +1,3 @@ +var fs = require("fs"); +console.log("I'm a .cjs file!"); +console.log(fs); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/ModuleTypes/import.js b/javascript/ql/test/library-tests/ModuleTypes/import.js new file mode 100644 index 00000000000..fc9423ddb3b --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/import.js @@ -0,0 +1,5 @@ +import * as fs from "fs"; + +export default function (x) { + return fs.readFileSync(x); +}; \ No newline at end of file diff --git a/javascript/ql/test/library-tests/ModuleTypes/mjs.mjs b/javascript/ql/test/library-tests/ModuleTypes/mjs.mjs new file mode 100644 index 00000000000..7c72272af5a --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/mjs.mjs @@ -0,0 +1 @@ +console.log("I'm a .mjs file!"); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/ModuleTypes/require.js b/javascript/ql/test/library-tests/ModuleTypes/require.js new file mode 100644 index 00000000000..982e834a4d4 --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/require.js @@ -0,0 +1,7 @@ +var fs = require("fs"); + +module.exports = { + foo: function (x) { + return fs.readFileSync(x); + } +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/ModuleTypes/script.js b/javascript/ql/test/library-tests/ModuleTypes/script.js new file mode 100644 index 00000000000..020c176d43f --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/script.js @@ -0,0 +1 @@ +console.log("I'm a plain script!"); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/ModuleTypes/tests.expected b/javascript/ql/test/library-tests/ModuleTypes/tests.expected new file mode 100644 index 00000000000..6aeb75cb04a --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/tests.expected @@ -0,0 +1,5 @@ +| commonjs.cjs:1:1:3:16 | | node | +| import.js:1:1:5:2 | | es2015 | +| mjs.mjs:1:1:1:32 | | es2015 | +| require.js:1:1:7:1 | | node | +| script.js:1:1:1:35 | | non-module | diff --git a/javascript/ql/test/library-tests/ModuleTypes/tests.ql b/javascript/ql/test/library-tests/ModuleTypes/tests.ql new file mode 100644 index 00000000000..45d1a927177 --- /dev/null +++ b/javascript/ql/test/library-tests/ModuleTypes/tests.ql @@ -0,0 +1,18 @@ +import javascript + +query string getModuleType(TopLevel top) { + not top.isExterns() and + ( + not top instanceof Module and + result = "non-module" + or + top instanceof NodeModule and + result = "node" + or + top instanceof ES2015Module and + result = "es2015" + or + top instanceof AmdModule and + result = "amd" + ) +} diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected index efbaad5a672..fa1d5872ecb 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected +++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSubstringSanitization.expected @@ -20,3 +20,6 @@ | tst-IncompleteUrlSubstringSanitization.js:63:4:63:33 | x.index ... !== -1 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:63:14:63:25 | "secure.com" | secure.com | | tst-IncompleteUrlSubstringSanitization.js:64:3:64:26 | x.inclu ... e.com") | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:64:14:64:25 | "secure.com" | secure.com | | tst-IncompleteUrlSubstringSanitization.js:66:6:66:29 | x.inclu ... e.com") | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:66:17:66:28 | "secure.com" | secure.com | +| tst-IncompleteUrlSubstringSanitization.js:73:5:73:48 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:73:15:73:42 | "https: ... oo/bar" | https://secure.com/foo/bar | +| tst-IncompleteUrlSubstringSanitization.js:74:5:74:40 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:74:15:74:34 | "https://secure.com" | https://secure.com | +| tst-IncompleteUrlSubstringSanitization.js:75:5:75:52 | x.index ... ") >= 0 | '$@' can be anywhere in the URL, and arbitrary hosts may come before or after it. | tst-IncompleteUrlSubstringSanitization.js:75:15:75:46 | "https: ... ar-baz" | https://secure.com/foo/bar-baz | diff --git a/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js b/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js index f7246c2a401..efbaaff1986 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js +++ b/javascript/ql/test/query-tests/Security/CWE-020/tst-IncompleteUrlSubstringSanitization.js @@ -67,5 +67,10 @@ } else { doSomeThingWithTrustedURL(x); - } + } + + x.startsWith("https://secure.com/foo/bar"); // OK - a forward slash after the domain makes prefix checks safe. + x.indexOf("https://secure.com/foo/bar") >= 0 // NOT OK - the url can be anywhere in the string. + x.indexOf("https://secure.com") >= 0 // NOT OK + x.indexOf("https://secure.com/foo/bar-baz") >= 0 // NOT OK - the url can be anywhere in the string. }); diff --git a/python/ql/src/Imports/UnintentionalImport.ql b/python/ql/src/Imports/UnintentionalImport.ql index dfd751fd527..2a3c2b6460b 100644 --- a/python/ql/src/Imports/UnintentionalImport.ql +++ b/python/ql/src/Imports/UnintentionalImport.ql @@ -26,7 +26,7 @@ predicate all_defined(ModuleValue exporter) { } from ImportStar imp, ModuleValue exporter -where import_star(imp, exporter) and not all_defined(exporter) +where import_star(imp, exporter) and not all_defined(exporter) and not exporter.isAbsent() select imp, "Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'.", exporter, exporter.getName() diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll index 5042dce683f..8c210edbe5f 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll @@ -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() } diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll index 5042dce683f..8c210edbe5f 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll @@ -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() } diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll b/python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll index 27ab1d01feb..892250f44bb 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll @@ -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 + ")") } diff --git a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll index 95c72ef7e14..1f46fd341e9 100644 --- a/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll +++ b/python/ql/src/experimental/dataflow/internal/DataFlowPrivate.qll @@ -97,8 +97,65 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { //-------- // Global flow //-------- +/** + * IPA type for DataFlowCallable. + * A callable is either a callable value or a class. + */ +newtype TDataFlowCallable = + TCallableValue(CallableValue callable) or + TClassValue(ClassValue c) + /** Represents a callable */ -class DataFlowCallable = CallableValue; +abstract class DataFlowCallable extends TDataFlowCallable { + /** Gets a textual representation of this element. */ + abstract string toString(); + + /** Gets a call to this callable. */ + abstract CallNode getACall(); + + /** Gets the scope of this callable */ + abstract Scope getScope(); + + /** Gets the specified parameter of this callable */ + abstract NameNode getParameter(int n); + + /** Gets the name of this callable. */ + abstract string getName(); +} + +class DataFlowCallableValue extends DataFlowCallable, TCallableValue { + CallableValue callable; + + DataFlowCallableValue() { this = TCallableValue(callable) } + + override string toString() { result = callable.toString() } + + override CallNode getACall() { result = callable.getACall() } + + override Scope getScope() { result = callable.getScope() } + + override NameNode getParameter(int n) { result = callable.getParameter(n) } + + override string getName() { result = callable.getName() } +} + +class DataFlowClassValue extends DataFlowCallable, TClassValue { + ClassValue c; + + DataFlowClassValue() { this = TClassValue(c) } + + override string toString() { result = c.toString() } + + override CallNode getACall() { result = c.getACall() } + + override Scope getScope() { result = c.getScope() } + + override NameNode getParameter(int n) { + result.getNode() = c.getScope().getInitMethod().getArg(n + 1).asName() + } + + override string getName() { result = c.getName() } +} /** Represents a call to a callable */ class DataFlowCall extends CallNode { diff --git a/python/ql/test/experimental/dataflow/basic/callGraph.ql b/python/ql/test/experimental/dataflow/basic/callGraph.ql index 53747b31739..2e8d6956c70 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraph.ql +++ b/python/ql/test/experimental/dataflow/basic/callGraph.ql @@ -1,4 +1,4 @@ -import callGraphConfig +import experimental.dataflow.callGraphConfig from DataFlow::Node source, DataFlow::Node sink where exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql b/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql index 020ea245cfd..7d15b353274 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql +++ b/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql @@ -1,4 +1,4 @@ -import callGraphConfig +import experimental.dataflow.callGraphConfig from DataFlow::Node sink where exists(CallGraphConfig cfg | cfg.isSink(sink)) diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSources.ql b/python/ql/test/experimental/dataflow/basic/callGraphSources.ql index a6bd5538866..21c3a5a9ace 100644 --- a/python/ql/test/experimental/dataflow/basic/callGraphSources.ql +++ b/python/ql/test/experimental/dataflow/basic/callGraphSources.ql @@ -1,4 +1,4 @@ -import callGraphConfig +import experimental.dataflow.callGraphConfig from DataFlow::Node source where exists(CallGraphConfig cfg | cfg.isSource(source)) diff --git a/python/ql/test/experimental/dataflow/basic/callGraphConfig.qll b/python/ql/test/experimental/dataflow/callGraphConfig.qll similarity index 100% rename from python/ql/test/experimental/dataflow/basic/callGraphConfig.qll rename to python/ql/test/experimental/dataflow/callGraphConfig.qll diff --git a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected index eaf7a166e23..2ae31eb1126 100644 --- a/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected +++ b/python/ql/test/experimental/dataflow/consistency/dataflow-consistency.expected @@ -101,3 +101,5 @@ argHasPostUpdate | test.py:74:17:74:17 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. | | test.py:81:13:81:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. | | test.py:86:13:86:13 | ControlFlowNode for t | ArgumentNode is missing PostUpdateNode. | +| test.py:158:15:158:15 | ControlFlowNode for l | ArgumentNode is missing PostUpdateNode. | +| test.py:159:15:159:15 | ControlFlowNode for d | ArgumentNode is missing PostUpdateNode. | diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py new file mode 100644 index 00000000000..de06d284361 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -0,0 +1,1228 @@ +# User-defined methods, both instance methods and class methods, can be called in many non-standard ways +# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` method on a +# class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`. +# +# These tests should cover all the class calls that we hope to support. +# It is based on https://docs.python.org/3/reference/datamodel.html, and headings refer there. +# +# All functions starting with "test_" should run and print `"OK"`. +# This can be checked by running validTest.py. + +def OK(): + print("OK") + +# object.__new__(cls[, ...]) +class With_new: + + def __new__(cls): + OK() + return super().__new__(cls) + +def test_new(): + with_new = With_new() + +# object.__init__(self[, ...]) +class With_init: + + def __init__(self): + OK() + +def test_init(): + with_init = With_init() + +# object.__del__(self) +class With_del: + + def __del__(self): + OK() + +def test_del(): + with_del = With_del() + del with_del + +# object.__repr__(self) +class With_repr: + + def __repr__(self): + OK() + return "With_repr()" + +def test_repr(): + with_repr = With_repr() + repr(with_repr) + +# object.__str__(self) +class With_str: + + def __str__(self): + OK() + return "Awesome" + +def test_str(): + with_str = With_str() + str(with_str) + +# object.__bytes__(self) +class With_bytes: + + def __bytes__(self): + OK() + return b"Awesome" + +def test_bytes(): + with_bytes = With_bytes() + bytes(with_bytes) + +# object.__format__(self, format_spec) +class With_format: + + def __format__(self, format_spec): + OK() + return "Awesome" + +def test_format(): + with_format = With_format() + format(with_format) + +def test_format_str(): + with_format = With_format() + "{0}".format(with_format) + +def test_format_fstr(): + with_format = With_format() + f"{with_format}" + +# object.__lt__(self, other) +class With_lt: + + def __lt__(self, other): + OK() + return "" + +def test_lt(): + with_lt = With_lt() + with_lt < with_lt + +# object.__le__(self, other) +class With_le: + + def __le__(self, other): + OK() + return "" + +def test_le(): + with_le = With_le() + with_le <= with_le + +# object.__eq__(self, other) +class With_eq: + + def __eq__(self, other): + OK() + return "" + +def test_eq(): + with_eq = With_eq() + with_eq == with_eq + +# object.__ne__(self, other) +class With_ne: + + def __ne__(self, other): + OK() + return "" + +def test_ne(): + with_ne = With_ne() + with_ne != with_ne + +# object.__gt__(self, other) +class With_gt: + + def __gt__(self, other): + OK() + return "" + +def test_gt(): + with_gt = With_gt() + with_gt > with_gt + +# object.__ge__(self, other) +class With_ge: + + def __ge__(self, other): + OK() + return "" + +def test_ge(): + with_ge = With_ge() + with_ge >= with_ge + +# object.__hash__(self) +class With_hash: + + def __hash__(self): + OK() + return 0 + +def test_hash(): + with_hash = With_hash() + hash(with_hash) + +def test_hash_set(): + with_hash = With_hash() + len(set([with_hash])) + +def test_hash_frozenset(): + with_hash = With_hash() + len(frozenset([with_hash])) + +def test_hash_dict(): + with_hash = With_hash() + len(dict({with_hash: 0})) + +# object.__bool__(self) +class With_bool: + + def __bool__(self): + OK() + return True + +def test_bool(): + with_bool = With_bool() + bool(with_bool) + +def test_bool_if(): + with_bool = With_bool() + if with_bool: + pass + +# 3.3.2. Customizing attribute access +# object.__getattr__(self, name) +class With_getattr: + + def __getattr__(self, name): + OK() + return "" + +def test_getattr(): + with_getattr = With_getattr() + with_getattr.foo + +# object.__getattribute__(self, name) +class With_getattribute: + + def __getattribute__(self, name): + OK() + return "" + +def test_getattribute(): + with_getattribute = With_getattribute() + with_getattribute.foo + +# object.__setattr__(self, name, value) +class With_setattr: + + def __setattr__(self, name, value): + OK() + +def test_setattr(): + with_setattr = With_setattr() + with_setattr.foo = "" + +# object.__delattr__(self, name) +class With_delattr: + + def __delattr__(self, name): + OK() + +def test_delattr(): + with_delattr = With_delattr() + del with_delattr.foo + +# object.__dir__(self) +class With_dir: + + def __dir__(self): + OK() + return [] + +def test_dir(): + with_dir = With_dir() + dir(with_dir) + + +# 3.3.2.2. Implementing Descriptors +class Owner: + pass + +# object.__get__(self, instance, owner=None) +class With_get: + + def __get__(self, instance, owner=None): + OK() + return "" + +def test_get(): + with_get = With_get() + Owner.attr = with_get + Owner.attr + +# object.__set__(self, instance, value) +class With_set: + + def __set__(self, instance, value): + OK() + +def test_set(): + with_set = With_set() + Owner.attr = with_set + owner = Owner() + owner.attr = "" + +# object.__delete__(self, instance) +class With_delete: + + def __delete__(self, instance): + OK() + +def test_delete(): + with_delete = With_delete() + Owner.attr = with_delete + owner = Owner() + del owner.attr + +# object.__set_name__(self, owner, name) +class With_set_name: + + def __set_name__(self, owner, name): + OK() + +def test_set_name(): + with_set_name = With_set_name() + type("Owner", (object,), dict(attr=with_set_name)) + +# 3.3.2.4. __slots__ // We are not testing the suppression of -weakref_ and _dict_ here +# object.__slots__ +# __weakref__ +# __dict__ + +# 3.3.3. Customizing class creation +# classmethod object.__init_subclass__(cls) +class With_init_subclass: + + def __init_subclass__(cls): + OK() + +def test_init_subclass(): + type("Subclass", (With_init_subclass,), {}) + +# 3.3.3.1. Metaclasses +# By default, classes are constructed using type(). The class body is executed in a new namespace and the class name is bound locally to the result of type(name, bases, namespace). + +# 3.3.3.2. Resolving MRO entries +# __mro_entries__ + +# 3.3.3.4. Preparing the class namespace +# metaclass.__prepare__(name, bases, **kwds) +class With_prepare(type): + + def __prepare__(name, bases, **kwds): + OK() + return kwds + + +def test_prepare(): + class With_meta(metaclass=With_prepare): + pass + +# 3.3.4. Customizing instance and subclass checks +# class.__instancecheck__(self, instance) +class With_instancecheck: + + def __instancecheck__(self, instance): + OK() + return True + +def test_instancecheck(): + with_instancecheck = With_instancecheck() + isinstance("", with_instancecheck) + +# class.__subclasscheck__(self, subclass) +class With_subclasscheck: + + def __subclasscheck__(self, subclass): + OK() + return True + +def test_subclasscheck(): + with_subclasscheck = With_subclasscheck() + issubclass(object, with_subclasscheck) + + +# 3.3.5. Emulating generic types +# classmethod object.__class_getitem__(cls, key) +class With_class_getitem: + + def __class_getitem__(cls, key): + OK() + return object + +def test_class_getitem(): + with_class_getitem = With_class_getitem[int]() + + +# 3.3.6. Emulating callable objects +# object.__call__(self[, args...]) +class With_call: + + def __call__(self): + OK() + +def test_call(): + with_call = With_call() + with_call() + +# 3.3.7. Emulating container types +# object.__len__(self) +class With_len: + + def __len__(self): + OK() + return 0 + +def test_len(): + with_len = With_len() + len(with_len) + +def test_len_bool(): + with_len = With_len() + bool(with_len) + +def test_len_if(): + with_len = With_len() + if with_len: + pass + +# object.__length_hint__(self) +class With_length_hint: + + def __length_hint__(self): + OK() + return 0 + +def test_length_hint(): + import operator + with_length_hint = With_length_hint() + operator.length_hint(with_length_hint) + +# object.__getitem__(self, key) +class With_getitem: + + def __getitem__(self, key): + OK() + return "" + +def test_getitem(): + with_getitem = With_getitem() + with_getitem[0] + +# object.__setitem__(self, key, value) +class With_setitem: + + def __setitem__(self, key, value): + OK() + +def test_setitem(): + with_setitem = With_setitem() + with_setitem[0] = "" + +# object.__delitem__(self, key) +class With_delitem: + + def __delitem__(self, key): + OK() + +def test_delitem(): + with_delitem = With_delitem() + del with_delitem[0] + +# object.__missing__(self, key) +class With_missing(dict): + + def __missing__(self, key): + OK() + return "" + +def test_missing(): + with_missing = With_missing() + with_missing[""] + +# object.__iter__(self) +class With_iter: + + def __iter__(self): + OK() + return [].__iter__() + +def test_iter(): + with_iter = With_iter() + [x for x in with_iter] + +# object.__reversed__(self) +class With_reversed: + + def __reversed__(self): + OK() + return [].__iter__ + +def test_reversed(): + with_reversed = With_reversed() + reversed(with_reversed) + +# object.__contains__(self, item) +class With_contains: + + def __contains__(self, item): + OK() + return True + +def test_contains(): + with_contains = With_contains() + 0 in with_contains + + +# 3.3.8. Emulating numeric types +# object.__add__(self, other) +class With_add: + + def __add__(self, other): + OK() + return self + +def test_add(): + with_add = With_add() + with_add + with_add + +# object.__sub__(self, other) +class With_sub: + + def __sub__(self, other): + OK() + return self + +def test_sub(): + with_sub = With_sub() + with_sub - with_sub + +# object.__mul__(self, other) +class With_mul: + + def __mul__(self, other): + OK() + return self + +def test_mul(): + with_mul = With_mul() + with_mul * with_mul + +# object.__matmul__(self, other) +class With_matmul: + + def __matmul__(self, other): + OK() + return self + +def test_matmul(): + with_matmul = With_matmul() + with_matmul @ with_matmul + +# object.__truediv__(self, other) +class With_truediv: + + def __truediv__(self, other): + OK() + return self + +def test_truediv(): + with_truediv = With_truediv() + with_truediv / with_truediv + +# object.__floordiv__(self, other) +class With_floordiv: + + def __floordiv__(self, other): + OK() + return self + +def test_floordiv(): + with_floordiv = With_floordiv() + with_floordiv // with_floordiv + +# object.__mod__(self, other) +class With_mod: + + def __mod__(self, other): + OK() + return self + +def test_mod(): + with_mod = With_mod() + with_mod % with_mod + +# object.__divmod__(self, other) +class With_divmod: + + def __divmod__(self, other): + OK() + return self + +def test_divmod(): + with_divmod = With_divmod() + divmod(with_divmod, with_divmod) + +# object.__pow__(self, other[, modulo]) +class With_pow: + + def __pow__(self, other): + OK() + return self + +def test_pow(): + with_pow = With_pow() + pow(with_pow, with_pow) + +def test_pow_op(): + with_pow = With_pow() + with_pow ** with_pow + +# object.__lshift__(self, other) +class With_lshift: + + def __lshift__(self, other): + OK() + return self + +def test_lshift(): + with_lshift = With_lshift() + with_lshift << with_lshift + +# object.__rshift__(self, other) +class With_rshift: + + def __rshift__(self, other): + OK() + return self + +def test_rshift(): + with_rshift = With_rshift() + with_rshift >> with_rshift + +# object.__and__(self, other) +class With_and: + + def __and__(self, other): + OK() + return self + +def test_and(): + with_and = With_and() + with_and & with_and + +# object.__xor__(self, other) +class With_xor: + + def __xor__(self, other): + OK() + return self + +def test_xor(): + with_xor = With_xor() + with_xor ^ with_xor + +# object.__or__(self, other) +class With_or: + + def __or__(self, other): + OK() + return self + +def test_or(): + with_or = With_or() + with_or | with_or + +# object.__radd__(self, other) +class With_radd: + + def __radd__(self, other): + OK() + return self + +def test_radd(): + with_radd = With_radd() + "" + with_radd + +# object.__rsub__(self, other) +class With_rsub: + + def __rsub__(self, other): + OK() + return self + +def test_rsub(): + with_rsub = With_rsub() + "" - with_rsub + +# object.__rmul__(self, other) +class With_rmul: + + def __rmul__(self, other): + OK() + return self + +def test_rmul(): + with_rmul = With_rmul() + "" * with_rmul + +# object.__rmatmul__(self, other) +class With_rmatmul: + + def __rmatmul__(self, other): + OK() + return self + +def test_rmatmul(): + with_rmatmul = With_rmatmul() + "" @ with_rmatmul + +# object.__rtruediv__(self, other) +class With_rtruediv: + + def __rtruediv__(self, other): + OK() + return self + +def test_rtruediv(): + with_rtruediv = With_rtruediv() + "" / with_rtruediv + +# object.__rfloordiv__(self, other) +class With_rfloordiv: + + def __rfloordiv__(self, other): + OK() + return self + +def test_rfloordiv(): + with_rfloordiv = With_rfloordiv() + "" // with_rfloordiv + +# object.__rmod__(self, other) +class With_rmod: + + def __rmod__(self, other): + OK() + return self + +def test_rmod(): + with_rmod = With_rmod() + {} % with_rmod + +# object.__rdivmod__(self, other) +class With_rdivmod: + + def __rdivmod__(self, other): + OK() + return self + +def test_rdivmod(): + with_rdivmod = With_rdivmod() + divmod("", with_rdivmod) + +# object.__rpow__(self, other[, modulo]) +class With_rpow: + + def __rpow__(self, other): + OK() + return self + +def test_rpow(): + with_rpow = With_rpow() + pow("", with_rpow) + +def test_rpow_op(): + with_rpow = With_rpow() + "" ** with_rpow + +# object.__rlshift__(self, other) +class With_rlshift: + + def __rlshift__(self, other): + OK() + return self + +def test_rlshift(): + with_rlshift = With_rlshift() + "" << with_rlshift + +# object.__rrshift__(self, other) +class With_rrshift: + + def __rrshift__(self, other): + OK() + return self + +def test_rrshift(): + with_rrshift = With_rrshift() + "" >> with_rrshift + +# object.__rand__(self, other) +class With_rand: + + def __rand__(self, other): + OK() + return self + +def test_rand(): + with_rand = With_rand() + "" & with_rand + +# object.__rxor__(self, other) +class With_rxor: + + def __rxor__(self, other): + OK() + return self + +def test_rxor(): + with_rxor = With_rxor() + "" ^ with_rxor + +# object.__ror__(self, other) +class With_ror: + + def __ror__(self, other): + OK() + return self + +def test_ror(): + with_ror = With_ror() + "" | with_ror + +# object.__iadd__(self, other) +class With_iadd: + + def __iadd__(self, other): + OK() + return self + +def test_iadd(): + with_iadd = With_iadd() + with_iadd += with_iadd + +# object.__isub__(self, other) +class With_isub: + + def __isub__(self, other): + OK() + return self + +def test_isub(): + with_isub = With_isub() + with_isub -= with_isub + +# object.__imul__(self, other) +class With_imul: + + def __imul__(self, other): + OK() + return self + +def test_imul(): + with_imul = With_imul() + with_imul *= with_imul + +# object.__imatmul__(self, other) +class With_imatmul: + + def __imatmul__(self, other): + OK() + return self + +def test_imatmul(): + with_imatmul = With_imatmul() + with_imatmul @= with_imatmul + +# object.__itruediv__(self, other) +class With_itruediv: + + def __itruediv__(self, other): + OK() + return self + +def test_itruediv(): + with_itruediv = With_itruediv() + with_itruediv /= with_itruediv + +# object.__ifloordiv__(self, other) +class With_ifloordiv: + + def __ifloordiv__(self, other): + OK() + return self + +def test_ifloordiv(): + with_ifloordiv = With_ifloordiv() + with_ifloordiv //= with_ifloordiv + +# object.__imod__(self, other) +class With_imod: + + def __imod__(self, other): + OK() + return self + +def test_imod(): + with_imod = With_imod() + with_imod %= with_imod + +# object.__ipow__(self, other[, modulo]) +class With_ipow: + + def __ipow__(self, other): + OK() + return self + +def test_ipow(): + with_ipow = With_ipow() + with_ipow **= with_ipow + +# object.__ilshift__(self, other) +class With_ilshift: + + def __ilshift__(self, other): + OK() + return self + +def test_ilshift(): + with_ilshift = With_ilshift() + with_ilshift <<= with_ilshift + +# object.__irshift__(self, other) +class With_irshift: + + def __irshift__(self, other): + OK() + return self + +def test_irshift(): + with_irshift = With_irshift() + with_irshift >>= with_irshift + +# object.__iand__(self, other) +class With_iand: + + def __iand__(self, other): + OK() + return self + +def test_iand(): + with_iand = With_iand() + with_iand &= with_iand + +# object.__ixor__(self, other) +class With_ixor: + + def __ixor__(self, other): + OK() + return self + +def test_ixor(): + with_ixor = With_ixor() + with_ixor ^= with_ixor + +# object.__ior__(self, other) +class With_ior: + + def __ior__(self, other): + OK() + return self + +def test_ior(): + with_ior = With_ior() + with_ior |= with_ior + +# object.__neg__(self) +class With_neg: + + def __neg__(self): + OK() + return self + +def test_neg(): + with_neg = With_neg() + -with_neg + +# object.__pos__(self) +class With_pos: + + def __pos__(self): + OK() + return self + +def test_pos(): + with_pos = With_pos() + +with_pos + +# object.__abs__(self) +class With_abs: + + def __abs__(self): + OK() + return self + +def test_abs(): + with_abs = With_abs() + abs(with_abs) + +# object.__invert__(self) +class With_invert: + + def __invert__(self): + OK() + return self + +def test_invert(): + with_invert = With_invert() + ~with_invert + +# object.__complex__(self) +class With_complex: + + def __complex__(self): + OK() + return 0j + +def test_complex(): + with_complex = With_complex() + complex(with_complex) + +# object.__int__(self) +class With_int: + + def __int__(self): + OK() + return 0 + +def test_int(): + with_int = With_int() + int(with_int) + +# object.__float__(self) +class With_float: + + def __float__(self): + OK() + return 0.0 + +def test_float(): + with_float = With_float() + float(with_float) + +# object.__index__(self) +class With_index: + + def __index__(self): + OK() + return 0 + +def test_index(): + import operator + with_index = With_index() + operator.index(with_index) + +def test_index_slicing(): + with_index = With_index() + [0][with_index:1] + +def test_index_bin(): + with_index = With_index() + bin(with_index) + +def test_index_hex(): + with_index = With_index() + hex(with_index) + +def test_index_oct(): + with_index = With_index() + oct(with_index) + +def test_index_int(): + with_index = With_index() + int(with_index) + +def test_index_float(): + with_index = With_index() + float(with_index) + +def test_index_complex(): + with_index = With_index() + complex(with_index) + +# object.__round__(self[, ndigits]) +class With_round: + + def __round__(self): + OK() + return 0 + +def test_round(): + with_round = With_round() + round(with_round) + +# object.__trunc__(self) +class With_trunc: + + def __trunc__(self): + OK() + return 0 + +def test_trunc(): + with_trunc = With_trunc() + import math + math.trunc(with_trunc) + +# object.__floor__(self) +class With_floor: + + def __floor__(self): + OK() + return 0 + +def test_floor(): + with_floor = With_floor() + import math + math.floor(with_floor) + +# object.__ceil__(self) +class With_ceil: + + def __ceil__(self): + OK() + return 0 + +def test_ceil(): + with_ceil = With_ceil() + import math + math.ceil(with_ceil) + + +# 3.3.9. With Statement Context Managers +# object.__enter__(self) +class With_enter: + + def __enter__(self): + OK() + return + + def __exit__(self, exc_type, exc_value, traceback): + return + +def test_enter(): + with With_enter(): + pass + +# object.__exit__(self, exc_type, exc_value, traceback) +class With_exit: + + def __enter__(self): + return + + def __exit__(self, exc_type, exc_value, traceback): + OK() + return + +def test_exit(): + with With_exit(): + pass + +# 3.4.1. Awaitable Objects +import asyncio + +# object.__await__(self) +class With_await: + + def __await__(self): + OK() + return (yield from asyncio.coroutine(lambda: "")()) + +async def atest_await(): + with_await = With_await() + await(with_await) + + +# # 3.4.2. Coroutine Objects // These should be handled as normal function calls +# # coroutine.send(value) +# # coroutine.throw(type[, value[, traceback]]) +# # coroutine.close() + +# 3.4.3. Asynchronous Iterators +# object.__aiter__(self) +class With_aiter: + + def __aiter__(self): + OK() + return self + + async def __anext__(self): + raise StopAsyncIteration + +async def atest_aiter(): + with_aiter = With_aiter() + async for x in with_aiter: + pass + +# object.__anext__(self) +class With_anext: + + def __aiter__(self): + return self + + async def __anext__(self): + OK() + raise StopAsyncIteration + +async def atest_anext(): + with_anext = With_anext() + async for x in with_anext: + pass + + +# 3.4.4. Asynchronous Context Managers +# object.__aenter__(self) +class With_aenter: + + async def __aenter__(self): + OK() + + async def __aexit__(self, exc_type, exc_value, traceback): + pass + +async def atest_aenter(): + with_aenter = With_aenter() + async with with_aenter: + pass + +# object.__aexit__(self, exc_type, exc_value, traceback) +class With_aexit: + + async def __aenter__(self): + pass + + async def __aexit__(self, exc_type, exc_value, traceback): + OK() + +async def atest_aexit(): + with_aexit = With_aexit() + async with with_aexit: + pass diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected new file mode 100644 index 00000000000..4baf0b077ab --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.expected @@ -0,0 +1,6 @@ +| classes.py:19:12:19:31 | ControlFlowNode for Attribute() | classes.py:19:12:19:31 | ControlFlowNode for Attribute() | +| classes.py:174:7:174:22 | ControlFlowNode for set() | classes.py:174:7:174:22 | ControlFlowNode for set() | +| classes.py:178:7:178:28 | ControlFlowNode for frozenset() | classes.py:178:7:178:28 | ControlFlowNode for frozenset() | +| classes.py:182:7:182:26 | ControlFlowNode for dict() | classes.py:182:7:182:26 | ControlFlowNode for dict() | +| classes.py:303:28:303:51 | ControlFlowNode for dict() | classes.py:303:28:303:51 | ControlFlowNode for dict() | +| classes.py:466:12:466:24 | ControlFlowNode for Attribute() | classes.py:466:12:466:24 | ControlFlowNode for Attribute() | diff --git a/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql new file mode 100644 index 00000000000..1445e314c98 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/classesCallGraph.ql @@ -0,0 +1,10 @@ +import experimental.dataflow.callGraphConfig + +from DataFlow::Node source, DataFlow::Node sink +where + source.getLocation().getFile().getBaseName() = "classes.py" and + sink.getLocation().getFile().getBaseName() = "classes.py" and + exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) +select source, sink +// Ideally, we would just have 1-step paths either from argument to parameter +// or from return to call. This gives a bit more, so should be rewritten. diff --git a/python/ql/test/experimental/dataflow/coverage/dataflow.expected b/python/ql/test/experimental/dataflow/coverage/dataflow.expected index cc8fd635e6b..2b446581634 100644 --- a/python/ql/test/experimental/dataflow/coverage/dataflow.expected +++ b/python/ql/test/experimental/dataflow/coverage/dataflow.expected @@ -1,39 +1,167 @@ edges -| test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x | -| test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x | -| test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x | -| test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | test.py:49:10:49:10 | ControlFlowNode for x | -| test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | test.py:53:10:53:10 | ControlFlowNode for x | -| test.py:61:10:61:15 | ControlFlowNode for SOURCE | test.py:62:10:62:10 | ControlFlowNode for x | -| test.py:238:28:238:33 | ControlFlowNode for SOURCE | test.py:238:10:238:34 | ControlFlowNode for second() | -| test.py:297:12:297:17 | ControlFlowNode for SOURCE | test.py:297:10:297:18 | ControlFlowNode for f() | -| test.py:301:28:301:33 | ControlFlowNode for SOURCE | test.py:301:10:301:34 | ControlFlowNode for second() | +| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | +| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:6:38:17 | GSSA Variable SOURCE | +| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | +| datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:13:1:13:6 | GSSA Variable SOURCE | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:65:5:65:7 | ControlFlowNode for C() | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:6:71:24 | GSSA Variable SOURCE | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | +| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | +| datamodel.py:65:1:65:1 | GSSA Variable c | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | +| datamodel.py:65:1:65:1 | GSSA Variable c | datamodel.py:71:6:71:24 | GSSA Variable c | +| datamodel.py:65:5:65:7 | ControlFlowNode for C() | datamodel.py:65:1:65:1 | GSSA Variable c | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:6:80:26 | GSSA Variable SOURCE | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | +| datamodel.py:71:6:71:24 | GSSA Variable c | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | +| datamodel.py:71:6:71:24 | GSSA Variable c | datamodel.py:72:6:72:27 | GSSA Variable c | +| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | +| datamodel.py:72:6:72:27 | GSSA Variable c | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | +| datamodel.py:72:6:72:27 | GSSA Variable c | datamodel.py:73:6:73:27 | GSSA Variable c | +| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | +| datamodel.py:73:6:73:27 | GSSA Variable c | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | +| datamodel.py:73:6:73:27 | GSSA Variable c | datamodel.py:80:6:80:26 | GSSA Variable c | +| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:6:81:26 | GSSA Variable SOURCE | +| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:92:8:92:21 | ControlFlowNode for gen() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable c | datamodel.py:96:9:96:24 | GSSA Variable c | +| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | +| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | +| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:92:8:92:21 | ControlFlowNode for gen() | +| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | datamodel.py:92:8:92:21 | GSSA Variable SOURCE | +| datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | +| datamodel.py:92:1:92:4 | GSSA Variable iter | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | +| datamodel.py:92:1:92:4 | GSSA Variable iter | datamodel.py:93:6:93:20 | GSSA Variable iter | +| datamodel.py:92:8:92:21 | ControlFlowNode for gen() | datamodel.py:92:1:92:4 | GSSA Variable iter | +| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | +| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | +| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | datamodel.py:96:9:96:24 | GSSA Variable SOURCE | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | +| datamodel.py:96:1:96:5 | GSSA Variable oiter | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | +| datamodel.py:96:1:96:5 | GSSA Variable oiter | datamodel.py:97:6:97:21 | GSSA Variable oiter | +| datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | datamodel.py:96:1:96:5 | GSSA Variable oiter | +| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | +| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | datamodel.py:106:18:106:29 | GSSA Variable SOURCE | +| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | +| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | +| datamodel.py:96:9:96:24 | GSSA Variable c | datamodel.py:107:18:107:31 | GSSA Variable c | +| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | +| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | +| datamodel.py:97:6:97:21 | GSSA Variable oiter | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | +| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | +| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | datamodel.py:107:18:107:31 | GSSA Variable SOURCE | +| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | +| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | datamodel.py:119:18:119:29 | GSSA Variable SOURCE | +| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | +| datamodel.py:107:18:107:31 | GSSA Variable c | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | +| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | +| test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x | +| test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x | +| test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x | +| test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x | +| test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x | +| test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x | +| test.py:246:28:246:33 | ControlFlowNode for SOURCE | test.py:246:10:246:34 | ControlFlowNode for second() | +| test.py:305:12:305:17 | ControlFlowNode for SOURCE | test.py:305:10:305:18 | ControlFlowNode for f() | +| test.py:309:28:309:33 | ControlFlowNode for SOURCE | test.py:309:10:309:34 | ControlFlowNode for second() | nodes -| test.py:35:9:35:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:36:10:36:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:40:9:40:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | -| test.py:41:10:41:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:44:9:44:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | -| test.py:45:10:45:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral | +| datamodel.py:13:1:13:6 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:13:10:13:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | +| datamodel.py:38:6:38:17 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| datamodel.py:38:6:38:17 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:65:1:65:1 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:65:5:65:7 | ControlFlowNode for C() | semmle.label | ControlFlowNode for C() | +| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:71:6:71:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:71:6:71:24 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:72:6:72:27 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | semmle.label | ControlFlowNode for func_obj() | +| datamodel.py:73:6:73:27 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:80:6:80:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:80:6:80:26 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:81:6:81:26 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | semmle.label | ControlFlowNode for c_func_obj() | +| datamodel.py:92:1:92:4 | GSSA Variable iter | semmle.label | GSSA Variable iter | +| datamodel.py:92:8:92:21 | ControlFlowNode for gen() | semmle.label | ControlFlowNode for gen() | +| datamodel.py:92:8:92:21 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:93:6:93:20 | GSSA Variable iter | semmle.label | GSSA Variable iter | +| datamodel.py:96:1:96:5 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | +| datamodel.py:96:9:96:24 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:96:9:96:24 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:96:9:96:24 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:97:6:97:21 | GSSA Variable oiter | semmle.label | GSSA Variable oiter | +| datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:106:18:106:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:107:18:107:31 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| datamodel.py:107:18:107:31 | GSSA Variable c | semmle.label | GSSA Variable c | +| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| datamodel.py:119:18:119:29 | GSSA Variable SOURCE | semmle.label | GSSA Variable SOURCE | +| test.py:43:9:43:14 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:44:10:44:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:48:9:48:16 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | | test.py:49:10:49:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral | +| test.py:52:9:52:17 | ControlFlowNode for Str | semmle.label | ControlFlowNode for Str | | test.py:53:10:53:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:61:10:61:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:62:10:62:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | -| test.py:238:10:238:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:238:28:238:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:297:10:297:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | -| test.py:297:12:297:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | -| test.py:301:10:301:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | -| test.py:301:28:301:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | semmle.label | ControlFlowNode for IntegerLiteral | +| test.py:57:10:57:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | semmle.label | ControlFlowNode for FloatLiteral | +| test.py:61:10:61:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:69:10:69:15 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:70:10:70:10 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | +| test.py:246:10:246:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:246:28:246:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:305:10:305:18 | ControlFlowNode for f() | semmle.label | ControlFlowNode for f() | +| test.py:305:12:305:17 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | +| test.py:309:10:309:34 | ControlFlowNode for second() | semmle.label | ControlFlowNode for second() | +| test.py:309:28:309:33 | ControlFlowNode for SOURCE | semmle.label | ControlFlowNode for SOURCE | #select -| test.py:36:10:36:10 | ControlFlowNode for x | test.py:35:9:35:14 | ControlFlowNode for SOURCE | test.py:36:10:36:10 | ControlFlowNode for x | | -| test.py:41:10:41:10 | ControlFlowNode for x | test.py:40:9:40:16 | ControlFlowNode for Str | test.py:41:10:41:10 | ControlFlowNode for x | | -| test.py:45:10:45:10 | ControlFlowNode for x | test.py:44:9:44:17 | ControlFlowNode for Str | test.py:45:10:45:10 | ControlFlowNode for x | | -| test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:10 | ControlFlowNode for IntegerLiteral | test.py:49:10:49:10 | ControlFlowNode for x | | -| test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:12 | ControlFlowNode for FloatLiteral | test.py:53:10:53:10 | ControlFlowNode for x | | -| test.py:62:10:62:10 | ControlFlowNode for x | test.py:61:10:61:15 | ControlFlowNode for SOURCE | test.py:62:10:62:10 | ControlFlowNode for x | | -| test.py:238:10:238:34 | ControlFlowNode for second() | test.py:238:28:238:33 | ControlFlowNode for SOURCE | test.py:238:10:238:34 | ControlFlowNode for second() | | -| test.py:297:10:297:18 | ControlFlowNode for f() | test.py:297:12:297:17 | ControlFlowNode for SOURCE | test.py:297:10:297:18 | ControlFlowNode for f() | | -| test.py:301:10:301:34 | ControlFlowNode for second() | test.py:301:28:301:33 | ControlFlowNode for SOURCE | test.py:301:10:301:34 | ControlFlowNode for second() | | +| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:38:6:38:17 | ControlFlowNode for f() | | +| datamodel.py:38:6:38:17 | ControlFlowNode for f() | datamodel.py:38:8:38:13 | ControlFlowNode for SOURCE | datamodel.py:38:6:38:17 | ControlFlowNode for f() | | +| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | | +| datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | datamodel.py:71:15:71:20 | ControlFlowNode for SOURCE | datamodel.py:71:6:71:24 | ControlFlowNode for Attribute() | | +| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | | +| datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | datamodel.py:72:18:72:23 | ControlFlowNode for SOURCE | datamodel.py:72:6:72:27 | ControlFlowNode for Attribute() | | +| datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:73:6:73:27 | ControlFlowNode for func_obj() | | +| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | | +| datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | datamodel.py:80:20:80:25 | ControlFlowNode for SOURCE | datamodel.py:80:6:80:26 | ControlFlowNode for Attribute() | | +| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | | +| datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | datamodel.py:81:20:81:25 | ControlFlowNode for SOURCE | datamodel.py:81:6:81:26 | ControlFlowNode for Attribute() | | +| datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:82:6:82:26 | ControlFlowNode for c_func_obj() | | +| datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:93:6:93:20 | ControlFlowNode for Attribute() | | +| datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:97:6:97:21 | ControlFlowNode for Attribute() | | +| datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:106:6:106:30 | ControlFlowNode for Attribute() | | +| datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:107:6:107:32 | ControlFlowNode for Attribute() | | +| datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | datamodel.py:13:10:13:17 | ControlFlowNode for Str | datamodel.py:119:6:119:30 | ControlFlowNode for Attribute() | | +| test.py:44:10:44:10 | ControlFlowNode for x | test.py:43:9:43:14 | ControlFlowNode for SOURCE | test.py:44:10:44:10 | ControlFlowNode for x | | +| test.py:49:10:49:10 | ControlFlowNode for x | test.py:48:9:48:16 | ControlFlowNode for Str | test.py:49:10:49:10 | ControlFlowNode for x | | +| test.py:53:10:53:10 | ControlFlowNode for x | test.py:52:9:52:17 | ControlFlowNode for Str | test.py:53:10:53:10 | ControlFlowNode for x | | +| test.py:57:10:57:10 | ControlFlowNode for x | test.py:56:9:56:10 | ControlFlowNode for IntegerLiteral | test.py:57:10:57:10 | ControlFlowNode for x | | +| test.py:61:10:61:10 | ControlFlowNode for x | test.py:60:9:60:12 | ControlFlowNode for FloatLiteral | test.py:61:10:61:10 | ControlFlowNode for x | | +| test.py:70:10:70:10 | ControlFlowNode for x | test.py:69:10:69:15 | ControlFlowNode for SOURCE | test.py:70:10:70:10 | ControlFlowNode for x | | +| test.py:246:10:246:34 | ControlFlowNode for second() | test.py:246:28:246:33 | ControlFlowNode for SOURCE | test.py:246:10:246:34 | ControlFlowNode for second() | | +| test.py:305:10:305:18 | ControlFlowNode for f() | test.py:305:12:305:17 | ControlFlowNode for SOURCE | test.py:305:10:305:18 | ControlFlowNode for f() | | +| test.py:309:10:309:34 | ControlFlowNode for second() | test.py:309:28:309:33 | ControlFlowNode for SOURCE | test.py:309:10:309:34 | ControlFlowNode for second() | | diff --git a/python/ql/test/experimental/dataflow/coverage/datamodel.py b/python/ql/test/experimental/dataflow/coverage/datamodel.py new file mode 100644 index 00000000000..a3fc54d11a0 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/datamodel.py @@ -0,0 +1,159 @@ +# User-defined methods, both instance methods and class methods, can be called in many non-standard ways +# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` method on a +# class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`. +# +# These tests are based on the first part of https://docs.python.org/3/reference/datamodel.html. +# A thorough covering of methods in that document is found in classes.py. +# +# Intended sources should be the variable `SOURCE` and intended sinks should be +# arguments to the function `SINK` (see python/ql/test/experimental/dataflow/testConfig.qll). + +# These are defined so that we can evaluate the test code. +NONSOURCE = "not a source" +SOURCE = "source" + +def is_source(x): + return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j + +def SINK(x): + if is_source(x): + print("OK") + else: + print("Unexpected flow", x) + +def SINK_F(x): + if is_source(x): + print("Unexpected flow", x) + else: + print("OK") + +# Callable types +# These are the types to which the function call operation (see section Calls) can be applied: + +# User-defined functions +# A user-defined function object is created by a function definition (see section Function definitions). It should be called with an argument list containing the same number of items as the function's formal parameter list. +def f(a, b): + return a + +SINK(f(SOURCE, 3)) + +# Instance methods +# An instance method object combines a class, a class instance and any callable object (normally a user-defined function). +class C(object): + + def method(self, x, cls): + assert cls is self.__class__ + return x + + @classmethod + def classmethod(cls, x): + return x + + @staticmethod + def staticmethod(x): + return x + + def gen(self, x, count): + n = count + while n > 0: + yield x + n -= 1 + + async def coro(self, x): + return x + +c = C() + +# When an instance method object is created by retrieving a user-defined function object from a class via one of its instances, its __self__ attribute is the instance, and the method object is said to be bound. The new method’s __func__ attribute is the original function object. +func_obj = c.method.__func__ + +# When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1). +SINK(c.method(SOURCE, C)) +SINK(C.method(c, SOURCE, C)) +SINK(func_obj(c, SOURCE, C)) + + +# When an instance method object is created by retrieving a class method object from a class or instance, its __self__ attribute is the class itself, and its __func__ attribute is the function object underlying the class method. +c_func_obj = C.classmethod.__func__ + +# When an instance method object is derived from a class method object, the “class instance” stored in __self__ will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function. +SINK(c.classmethod(SOURCE)) +SINK(C.classmethod(SOURCE)) +SINK(c_func_obj(C, SOURCE)) + +# Generator functions +# A function or method which uses the yield statement (see section The yield statement) is called a generator function. Such a function, when called, always returns an iterator object which can be used to execute the body of the function: calling the iterator’s iterator.__next__() method will cause the function to execute until it provides a value using the yield statement. When the function executes a return statement or falls off the end, a StopIteration exception is raised and the iterator will have reached the end of the set of values to be returned. +def gen(x, count): + n = count + while n > 0: + yield x + n -= 1 + +iter = gen(SOURCE, 1) +SINK(iter.__next__()) +# SINK_F(iter.__next__()) # throws StopIteration, FP + +oiter = c.gen(SOURCE, 1) +SINK(oiter.__next__()) +# SINK_F(oiter.__next__()) # throws StopIteration, FP + +# Coroutine functions +# A function or method which is defined using async def is called a coroutine function. Such a function, when called, returns a coroutine object. It may contain await expressions, as well as async with and async for statements. See also the Coroutine Objects section. +async def coro(x): + return x + +import asyncio +SINK(asyncio.run(coro(SOURCE))) +SINK(asyncio.run(c.coro(SOURCE))) + +class A: + + def __await__(self): + # yield SOURCE -- see https://groups.google.com/g/dev-python/c/_lrrc-vp9TI?pli=1 + return (yield from asyncio.coroutine(lambda: SOURCE)()) + +async def agen(x): + a = A() + return await a + +SINK(asyncio.run(agen(SOURCE))) + +# Asynchronous generator functions +# A function or method which is defined using async def and which uses the yield statement is called a asynchronous generator function. Such a function, when called, returns an asynchronous iterator object which can be used in an async for statement to execute the body of the function. + +# Calling the asynchronous iterator’s aiterator.__anext__() method will return an awaitable which when awaited will execute until it provides a value using the yield expression. When the function executes an empty return statement or falls off the end, a StopAsyncIteration exception is raised and the asynchronous iterator will have reached the end of the set of values to be yielded. + +# Built-in functions +# A built-in function object is a wrapper around a C function. Examples of built-in functions are len() and math.sin() (math is a standard built-in module). The number and type of the arguments are determined by the C function. Special read-only attributes: __doc__ is the function’s documentation string, or None if unavailable; __name__ is the function’s name; __self__ is set to None (but see the next item); __module__ is the name of the module the function was defined in or None if unavailable. + +# Built-in methods +# This is really a different disguise of a built-in function, this time containing an object passed to the C function as an implicit extra argument. An example of a built-in method is alist.append(), assuming alist is a list object. In this case, the special read-only attribute __self__ is set to the object denoted by alist. + +# Classes +# Classes are callable. These objects normally act as factories for new instances of themselves, but variations are possible for class types that override __new__(). The arguments of the call are passed to __new__() and, in the typical case, to __init__() to initialize the new instance. + +# Class Instances +# Instances of arbitrary classes can be made callable by defining a __call__() method in their class. + +# If a class sets __iter__() to None, calling iter() on its instances will raise a TypeError (without falling back to __getitem__()). + +# 3.3.1. Basic customization + +class Customized: + + a = NONSOURCE + b = NONSOURCE + + def __new__(cls): + cls.a = SOURCE + return super().__new__(cls) + + def __init__(self): + self.b = SOURCE + +# testing __new__ and __init__ +customized = Customized() +SINK(Customized.a) +SINK_F(Customized.b) +SINK(customized.a) +SINK(customized.b) diff --git a/python/ql/test/experimental/dataflow/coverage/localFlow.expected b/python/ql/test/experimental/dataflow/coverage/localFlow.expected index eee5e093f5e..9e4dc40eafc 100644 --- a/python/ql/test/experimental/dataflow/coverage/localFlow.expected +++ b/python/ql/test/experimental/dataflow/coverage/localFlow.expected @@ -1,7 +1,7 @@ -| test.py:24:5:24:5 | SSA variable x | test.py:23:1:23:33 | Exit node for Function test_tuple_with_local_flow | -| test.py:24:5:24:5 | SSA variable x | test.py:25:9:25:9 | ControlFlowNode for x | -| test.py:24:10:24:26 | ControlFlowNode for Tuple | test.py:24:5:24:5 | SSA variable x | -| test.py:25:5:25:5 | SSA variable y | test.py:26:5:26:11 | SSA variable y | -| test.py:25:5:25:5 | SSA variable y | test.py:26:10:26:10 | ControlFlowNode for y | -| test.py:25:9:25:12 | ControlFlowNode for Subscript | test.py:25:5:25:5 | SSA variable y | -| test.py:26:5:26:11 | SSA variable y | test.py:23:1:23:33 | Exit node for Function test_tuple_with_local_flow | +| test.py:32:5:32:5 | SSA variable x | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow | +| test.py:32:5:32:5 | SSA variable x | test.py:33:9:33:9 | ControlFlowNode for x | +| test.py:32:10:32:26 | ControlFlowNode for Tuple | test.py:32:5:32:5 | SSA variable x | +| test.py:33:5:33:5 | SSA variable y | test.py:34:5:34:11 | SSA variable y | +| test.py:33:5:33:5 | SSA variable y | test.py:34:10:34:10 | ControlFlowNode for y | +| test.py:33:9:33:12 | ControlFlowNode for Subscript | test.py:33:5:33:5 | SSA variable y | +| test.py:34:5:34:11 | SSA variable y | test.py:31:1:31:33 | Exit node for Function test_tuple_with_local_flow | diff --git a/python/ql/test/experimental/dataflow/coverage/test.py b/python/ql/test/experimental/dataflow/coverage/test.py index 0324fd6a7f9..c3c0702f1a8 100644 --- a/python/ql/test/experimental/dataflow/coverage/test.py +++ b/python/ql/test/experimental/dataflow/coverage/test.py @@ -6,19 +6,27 @@ # # Functions whose name ends with "_with_local_flow" will also be tested for local flow. # -# All functions starting with "test_" should run and either -# - print a source (sources are defined in testConfig.qll). -# - print "Unexpected flow: " and a non-source -# (The idea is to later write a script to autimatically confirm this.) +# All functions starting with "test_" should run and print `"OK"`. +# This can be checked by running validTest.py. # These are defined so that we can evaluate the test code. NONSOURCE = "not a source" SOURCE = "source" + +def is_source(x): + return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j + def SINK(x): - print(x) + if is_source(x): + print("OK") + else: + print("Unexpected flow", x) def SINK_F(x): - print("Unexpected flow: ", x) + if is_source(x): + print("Unexpected flow", x) + else: + print("OK") def test_tuple_with_local_flow(): x = (NONSOURCE, SOURCE) diff --git a/python/ql/test/experimental/dataflow/coverage/validTest.py b/python/ql/test/experimental/dataflow/coverage/validTest.py new file mode 100644 index 00000000000..cec82c47723 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage/validTest.py @@ -0,0 +1,49 @@ +def check_output(s, f): + if s == "OK\n": + pass + else: + raise RuntimeError("Function failed", s, f) + +def check_test_function(f): + from io import StringIO + import sys + + capturer = StringIO() + old_stdout = sys.stdout + sys.stdout = capturer + f() + sys.stdout = old_stdout + check_output(capturer.getvalue(), f) + +def check_async_test_function(f): + from io import StringIO + import sys + import asyncio + + capturer = StringIO() + old_stdout = sys.stdout + sys.stdout = capturer + asyncio.run(f()) + sys.stdout = old_stdout + check_output(capturer.getvalue(), f) + +def check_tests_valid(testFile): + import importlib + tests = importlib.import_module(testFile) + for i in dir(tests): + # print("Considering", i) + if i.startswith("test_"): + item = getattr(tests,i) + if callable(item): + print("Checking", testFile, item) + check_test_function(item) + + elif i.startswith("atest_"): + item = getattr(tests,i) + if callable(item): + print("Checking", testFile, item) + check_async_test_function(item) + +if __name__ == '__main__': + check_tests_valid("classes") + check_tests_valid("test") diff --git a/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected b/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected index 9aa101edbca..d29bc2b9b5f 100644 --- a/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected +++ b/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected @@ -1,2 +1,3 @@ | imports_test.py:21:1:21:20 | from module import * | Using 'from ... import *' pollutes the namespace | | imports_test.py:22:1:22:32 | from module_without_all import * | Using 'from ... import *' pollutes the namespace | +| imports_test.py:65:1:65:40 | from module_that_does_not_exist import * | Using 'from ... import *' pollutes the namespace | diff --git a/python/ql/test/query-tests/Imports/general/imports_test.py b/python/ql/test/query-tests/Imports/general/imports_test.py index 5e5184b78c7..4b51f8254fc 100644 --- a/python/ql/test/query-tests/Imports/general/imports_test.py +++ b/python/ql/test/query-tests/Imports/general/imports_test.py @@ -61,3 +61,5 @@ import module1 as different #Use it different +# FP reported in https://github.com/github/codeql/issues/4003 +from module_that_does_not_exist import *